SQL-based authentication: Difference between revisions
Content added Content deleted
m (→{{header|Phix}}: syntax coloured, marked p2js incompatible) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 7: | Line 7: | ||
This is the table definition: |
This is the table definition: |
||
< |
<syntaxhighlight lang="sql">create table users ( |
||
userid int primary key auto_increment, |
userid int primary key auto_increment, |
||
username varchar(32) unique key not null, |
username varchar(32) unique key not null, |
||
Line 14: | Line 14: | ||
pass_md5 tinyblob not null |
pass_md5 tinyblob not null |
||
-- binary MD5 hash of pass_salt concatenated with the password |
-- binary MD5 hash of pass_salt concatenated with the password |
||
);</ |
);</syntaxhighlight> |
||
(<tt>pass_salt</tt> and <tt>pass_md5</tt> would be <tt>binary(16)</tt> values, but MySQL versions before 5.0.15 strip trailing spaces when selecting them.) |
(<tt>pass_salt</tt> and <tt>pass_md5</tt> would be <tt>binary(16)</tt> values, but MySQL versions before 5.0.15 strip trailing spaces when selecting them.) |
||
Line 20: | Line 20: | ||
{{libheader|mysqlclient}} (MySQL client library) |
{{libheader|mysqlclient}} (MySQL client library) |
||
{{libheader|OpenSSL}} (for MD5) |
{{libheader|OpenSSL}} (for MD5) |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
#include <string.h> |
#include <string.h> |
||
Line 193: | Line 193: | ||
} |
} |
||
return EXIT_SUCCESS; |
return EXIT_SUCCESS; |
||
}</ |
}</syntaxhighlight> |
||
From the command line, <tt>program add user password</tt> to add users, and <tt>program auth user password</tt> to see if the user with that password is authorized or not. |
From the command line, <tt>program add user password</tt> to add users, and <tt>program auth user password</tt> to see if the user with that password is authorized or not. |
||
Line 199: | Line 199: | ||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
Class for hashing and random salt generation. |
Class for hashing and random salt generation. |
||
< |
<syntaxhighlight lang="csharp">using System.Security.Cryptography; |
||
using System.Text; |
using System.Text; |
||
Line 236: | Line 236: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Class for creating and authenticating users. |
Class for creating and authenticating users. |
||
< |
<syntaxhighlight lang="csharp">using MySql.Data.MySqlClient; |
||
namespace rosettaMySQL |
namespace rosettaMySQL |
||
Line 302: | Line 302: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Class with main method and database connection method. |
Class with main method and database connection method. |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using MySql.Data.MySqlClient; |
using MySql.Data.MySqlClient; |
||
Line 356: | Line 356: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Output |
Output |
||
<pre>Bob has been created: True |
<pre>Bob has been created: True |
||
Line 364: | Line 364: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 442: | Line 442: | ||
// clear table to run program again |
// clear table to run program again |
||
db.Exec(`truncate table users`) |
db.Exec(`truncate table users`) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 455: | Line 455: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{works with|Java|1.7}} |
{{works with|Java|1.7}} |
||
< |
<syntaxhighlight lang="java">import java.io.UnsupportedEncodingException; |
||
import java.sql.Connection; |
import java.sql.Connection; |
||
import java.sql.DriverManager; |
import java.sql.DriverManager; |
||
Line 596: | Line 596: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia"> |
||
using MySQL |
using MySQL |
||
using Nettle # for md5 |
using Nettle # for md5 |
||
Line 648: | Line 648: | ||
println("""Mary does not authenticate with password of 123: $(authenticate_user(mydb, "Mary", "123")==false)""") |
println("""Mary does not authenticate with password of 123: $(authenticate_user(mydb, "Mary", "123")==false)""") |
||
mysql_disconnect(mydb) |
mysql_disconnect(mydb) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="scala">// Version 1.2.41 |
||
import java.sql.Connection |
import java.sql.Connection |
||
Line 752: | Line 752: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
{{libheader|DatabaseLink`}} |
{{libheader|DatabaseLink`}} |
||
< |
<syntaxhighlight lang="mathematica">Needs["DatabaseLink`"]; |
||
connectDb[dbUser_, dbPass_, dbUrl_] := |
connectDb[dbUser_, dbPass_, dbUrl_] := |
||
OpenSQLConnection[JDBC["mysql", dbUrl], "Username" -> dbUser, |
OpenSQLConnection[JDBC["mysql", dbUrl], "Username" -> dbUser, |
||
Line 779: | Line 779: | ||
SQLColumn["username"] == user][[1]]}, |
SQLColumn["username"] == user][[1]]}, |
||
Hash[FromCharacterCode[data[[2, 1]]] <> pass, "MD5"] == |
Hash[FromCharacterCode[data[[2, 1]]] <> pass, "MD5"] == |
||
FromDigits[data[[3, 1]], 256]]; CloseSQLConnection[db]; rtn];</ |
FromDigits[data[[3, 1]], 256]]; CloseSQLConnection[db]; rtn];</syntaxhighlight> |
||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
Line 785: | Line 785: | ||
Even if this program is only an example, we have chosen to generate the salt using the random number generator provided by the third-party module “nimcrypto” rather than using the PRNG from the standard module “random” which is totally inadequate for cryptographic usage. |
Even if this program is only an example, we have chosen to generate the salt using the random number generator provided by the third-party module “nimcrypto” rather than using the PRNG from the standard module “random” which is totally inadequate for cryptographic usage. |
||
< |
<syntaxhighlight lang="nim">import db_mysql, nimcrypto, md5, strutils |
||
proc connectDb(user, password: string): DbConn = |
proc connectDb(user, password: string): DbConn = |
||
Line 850: | Line 850: | ||
# Clean-up and close. |
# Clean-up and close. |
||
db.clean() |
db.clean() |
||
db.close()</ |
db.close()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 858: | Line 858: | ||
=={{header|Objeck}}== |
=={{header|Objeck}}== |
||
< |
<syntaxhighlight lang="objeck">use ODBC; |
||
use Encryption; |
use Encryption; |
||
Line 961: | Line 961: | ||
return true; |
return true; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
Line 967: | Line 967: | ||
{{libheader|DBI}}<br> |
{{libheader|DBI}}<br> |
||
{{libheader|DBD::mysql}} |
{{libheader|DBD::mysql}} |
||
< |
<syntaxhighlight lang="perl">use DBI; |
||
# returns a database handle configured to throw an exception on query errors |
# returns a database handle configured to throw an exception on query errors |
||
Line 996: | Line 996: | ||
undef, $user, $pass); |
undef, $user, $pass); |
||
$userid |
$userid |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Uses SQLite, there is a MySQL wrapper in [http://phix.x10.mx/pmwiki/pmwiki.php PCAN] that I have not personally tried yet.<br> |
Uses SQLite, there is a MySQL wrapper in [http://phix.x10.mx/pmwiki/pmwiki.php PCAN] that I have not personally tried yet.<br> |
||
Uses code from [[MD5/Implementation#Phix|MD5]], now modified to be an executable library. |
Uses code from [[MD5/Implementation#Phix|MD5]], now modified to be an executable library. |
||
<!--< |
<!--<syntaxhighlight lang="phix">(notonline)--> |
||
<span style="color: #000080;font-style:italic;">-- demo\rosetta\SQL-based_authentication.exw</span> |
<span style="color: #000080;font-style:italic;">-- demo\rosetta\SQL-based_authentication.exw</span> |
||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (file i/o)</span> |
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (file i/o)</span> |
||
Line 1,076: | Line 1,076: | ||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
||
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,085: | Line 1,085: | ||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
To use MySQL in PHP you need the php_mysql module installed |
To use MySQL in PHP you need the php_mysql module installed |
||
< |
<syntaxhighlight lang="php"> |
||
function connect_db($database, $db_user, $db_password, $host = 'localhost', $port = NULL, $die = false) { |
function connect_db($database, $db_user, $db_password, $host = 'localhost', $port = NULL, $die = false) { |
||
// Returns a MySQL link identifier (handle) on success |
// Returns a MySQL link identifier (handle) on success |
||
Line 1,155: | Line 1,155: | ||
return $row['userid']; |
return $row['userid']; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{works with|Python|2.7}} |
{{works with|Python|2.7}} |
||
Uses the [http://dev.mysql.com/downloads/connector/python/ official Python MySQL connector] |
Uses the [http://dev.mysql.com/downloads/connector/python/ official Python MySQL connector] |
||
< |
<syntaxhighlight lang="python">import mysql.connector |
||
import hashlib |
import hashlib |
||
Line 1,242: | Line 1,242: | ||
else: |
else: |
||
print 'User %s failed' % user |
print 'User %s failed' % user |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(require db file/md5) |
(require db file/md5) |
||
(define-logger authentication) |
(define-logger authentication) |
||
Line 1,310: | Line 1,310: | ||
(check-false (create-user test-DB #"tim" #"tim's password")) |
(check-false (create-user test-DB #"tim" #"tim's password")) |
||
(check-exn exn:fail? (λ () (authenticate-user test-DB #"tim" #"password"))) |
(check-exn exn:fail? (λ () (authenticate-user test-DB #"tim" #"password"))) |
||
(check-true (authenticate-user test-DB #"tim" #"shh! it's a secret!")))</ |
(check-true (authenticate-user test-DB #"tim" #"shh! it's a secret!")))</syntaxhighlight> |
||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(formerly Perl 6) |
||
{{trans|Perl}} |
{{trans|Perl}} |
||
<syntaxhighlight lang="raku" line> |
|||
<lang perl6> |
|||
use v6; |
use v6; |
||
use DBIish; |
use DBIish; |
||
Line 1,344: | Line 1,344: | ||
my $userid = $sth.fetch; |
my $userid = $sth.fetch; |
||
$userid[0] or Any; |
$userid[0] or Any; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Raven}}== |
=={{header|Raven}}== |
||
MySQL connectivity is available out of the box. Below, we do not ever send the plain text password over the wire. |
MySQL connectivity is available out of the box. Below, we do not ever send the plain text password over the wire. |
||
< |
<syntaxhighlight lang="raven"> 'mysql://root@localhost/test' open as mysql |
||
'abcdefghijklmnopqrstuvwxyz0123456789' as $salt_chars |
'abcdefghijklmnopqrstuvwxyz0123456789' as $salt_chars |
||
Line 1,379: | Line 1,379: | ||
'foo' 'bar' authenticate_user !if "could not authenticate user\n" print bye |
'foo' 'bar' authenticate_user !if "could not authenticate user\n" print bye |
||
"user successfully created and authenticated!\n" print</ |
"user successfully created and authenticated!\n" print</syntaxhighlight> |
||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
Uses the [https://github.com/brianmario/mysql2 mysql2 gem] |
Uses the [https://github.com/brianmario/mysql2 mysql2 gem] |
||
< |
<syntaxhighlight lang="ruby">require 'mysql2' |
||
require 'securerandom' |
require 'securerandom' |
||
require 'digest' |
require 'digest' |
||
Line 1,412: | Line 1,412: | ||
password_md5 = Digest::MD5.hexdigest(user_record['pass_salt'] + password) |
password_md5 = Digest::MD5.hexdigest(user_record['pass_salt'] + password) |
||
password_md5 == user_record['pass_md5'] |
password_md5 == user_record['pass_md5'] |
||
end</ |
end</syntaxhighlight> |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
{{trans|Perl}} |
{{trans|Perl}} |
||
< |
<syntaxhighlight lang="ruby">require('DBI') |
||
# returns a database handle configured to throw an exception on query errors |
# returns a database handle configured to throw an exception on query errors |
||
Line 1,442: | Line 1,442: | ||
nil, user, pass |
nil, user, pass |
||
) |
) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
{{works with|Tcl|8.6}} |
{{works with|Tcl|8.6}} |
||
Also requires the TDBC driver for MySQL. |
Also requires the TDBC driver for MySQL. |
||
< |
<syntaxhighlight lang="tcl">package require tdbc |
||
proc connect_db {handleName dbname host user pass} { |
proc connect_db {handleName dbname host user pass} { |
||
Line 1,482: | Line 1,482: | ||
# Only get here if no rows selected |
# Only get here if no rows selected |
||
error "authentication failed for user \"$user\"" |
error "authentication failed for user \"$user\"" |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
Line 1,491: | Line 1,491: | ||
Not an exact 'phiximile' but follows the same lines. |
Not an exact 'phiximile' but follows the same lines. |
||
< |
<syntaxhighlight lang="ecmascript">import "./sql" for Sql, Connection |
||
import "./crypto" for Md5 |
import "./crypto" for Md5 |
||
Line 1,533: | Line 1,533: | ||
addUser.call(db, "user", "password") |
addUser.call(db, "user", "password") |
||
System.print("User with correct password: %(authenticateUser.call(db, "user", "password"))") |
System.print("User with correct password: %(authenticateUser.call(db, "user", "password"))") |
||
System.print("User with incorrect password: %(authenticateUser.call(db, "user", "wrong"))")</ |
System.print("User with incorrect password: %(authenticateUser.call(db, "user", "wrong"))")</syntaxhighlight> |
||
{{out}} |
{{out}} |