SQL-based authentication: Difference between revisions

Content added Content deleted
m (→‎{{header|Phix}}: syntax coloured, marked p2js incompatible)
m (syntax highlighting fixup automation)
Line 7: Line 7:


This is the table definition:
This is the table definition:
<lang sql>create table users (
<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
);</lang>
);</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)
<lang c>#include <stdio.h>
<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;
}</lang>
}</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.
<lang csharp>using System.Security.Cryptography;
<syntaxhighlight lang="csharp">using System.Security.Cryptography;
using System.Text;
using System.Text;


Line 236: Line 236:
}
}
}
}
}</lang>
}</syntaxhighlight>
Class for creating and authenticating users.
Class for creating and authenticating users.
<lang csharp>using MySql.Data.MySqlClient;
<syntaxhighlight lang="csharp">using MySql.Data.MySqlClient;


namespace rosettaMySQL
namespace rosettaMySQL
Line 302: Line 302:
}
}
}
}
}</lang>
}</syntaxhighlight>
Class with main method and database connection method.
Class with main method and database connection method.
<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;
using MySql.Data.MySqlClient;
using MySql.Data.MySqlClient;


Line 356: Line 356:
}
}
}
}
}</lang>
}</syntaxhighlight>
Output
Output
<pre>Bob has been created: True
<pre>Bob has been created: True
Line 364: Line 364:


=={{header|Go}}==
=={{header|Go}}==
<lang go>package main
<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`)
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 455: Line 455:
=={{header|Java}}==
=={{header|Java}}==
{{works with|Java|1.7}}
{{works with|Java|1.7}}
<lang java>import java.io.UnsupportedEncodingException;
<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:
}
}
}
}
}</lang>
}</syntaxhighlight>


=={{header|Julia}}==
=={{header|Julia}}==
<lang 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}}
<lang scala>// Version 1.2.41
<syntaxhighlight lang="scala">// Version 1.2.41


import java.sql.Connection
import java.sql.Connection
Line 752: Line 752:
}
}
}
}
}</lang>
}</syntaxhighlight>


=={{header|Mathematica}}/{{header|Wolfram Language}}==
=={{header|Mathematica}}/{{header|Wolfram Language}}==
{{libheader|DatabaseLink`}}
{{libheader|DatabaseLink`}}
<lang Mathematica>Needs["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];</lang>
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.


<lang Nim>import db_mysql, nimcrypto, md5, strutils
<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()</lang>
db.close()</syntaxhighlight>


{{out}}
{{out}}
Line 858: Line 858:


=={{header|Objeck}}==
=={{header|Objeck}}==
<lang objeck>use ODBC;
<syntaxhighlight lang="objeck">use ODBC;
use Encryption;
use Encryption;


Line 961: Line 961:
return true;
return true;
}
}
}</lang>
}</syntaxhighlight>


=={{header|Perl}}==
=={{header|Perl}}==
Line 967: Line 967:
{{libheader|DBI}}<br>
{{libheader|DBI}}<br>
{{libheader|DBD::mysql}}
{{libheader|DBD::mysql}}
<lang perl>use DBI;
<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
}</lang>
}</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.
<!--<lang Phix>(notonline)-->
<!--<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>
<!--</lang>-->
<!--</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
<lang php>
<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]
<lang python>import 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}}==


<lang racket>#lang 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!")))</lang>
(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;
}</lang>
}</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.


<lang raven> 'mysql://root@localhost/test' open as mysql
<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</lang>
"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]
<lang ruby>require 'mysql2'
<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</lang>
end</syntaxhighlight>


=={{header|Sidef}}==
=={{header|Sidef}}==
{{trans|Perl}}
{{trans|Perl}}
<lang ruby>require('DBI')
<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
)
)
}</lang>
}</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.
<lang Tcl>package require tdbc
<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\""
}</lang>
}</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.
<lang ecmascript>import "./sql" for Sql, Connection
<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"))")</lang>
System.print("User with incorrect password: %(authenticateUser.call(db, "user", "wrong"))")</syntaxhighlight>


{{out}}
{{out}}