3 * A special authenticator for SQLite.
5 * Copyright 2003 Mark O'Sullivan
6 * This file is part of Lussumo's Software Library.
7 * Lussumo's Software Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
8 * Lussumo's Software Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9 * You should have received a copy of the GNU General Public License along with Vanilla; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10 * The latest source code is available at www.lussumo.com
11 * Contact Mark O'Sullivan at mark [at] lussumo [dot] com
13 * @author Mark O'Sullivan
14 * @copyright 2003 Mark O'Sullivan
15 * @license http://lussumo.com/community/gpl.txt GPL 2
22 * A special authenticator for SQLite.
28 // Returning '0' indicates that the username and password combination weren't found.
29 // Returning '-1' indicates that the user does not have permission to sign in.
30 // Returning '-2' indicates that a fatal error has occurred while querying the database.
31 function Authenticate($Username, $Password, $PersistentSession) {
32 // Validate the username and password that have been set
33 $Username = FormatStringForDatabaseInput($Username);
34 $Password = FormatStringForDatabaseInput($Password);
37 // Retrieve matching username/password values
38 $Query = "select u.UserID, r.PERMISSION_SIGN_IN
39 from ".$this->Context
->Configuration
['DATABASE_TABLE_PREFIX']."User u
40 inner join ".$this->Context
->Configuration
['DATABASE_TABLE_PREFIX']."Role r
41 on u.RoleID = r.RoleID
42 where u.Name = '".$Username."'
43 and u.Password = '".$Password."'";
45 $UserResult = $this->Context
->Database
->Execute($Query,
48 'An error occurred while attempting to validate your credentials');
52 } elseif ($this->Context
->Database
->RowCount($UserResult) > 0) {
54 $EncryptedUserID = '';
55 $VerificationKey = '';
56 while ($rows = $this->Context
->Database
->GetRow($UserResult)) {
57 $EncryptedUserID = md5($rows['UserID']);
58 $VerificationKey = DefineVerificationKey();
59 $UserID = ForceInt($rows['UserID'], 0);
60 $CanSignIn = ForceBool($rows['PERMISSION_SIGN_IN'], 0);
65 // Update the user's information
66 $this->UpdateLastVisit($UserID, $VerificationKey);
68 // Assign the session value
69 $this->AssignSessionUserID($UserID);
71 // Set the 'remember me' cookies
72 if ($PersistentSession) $this->SetCookieCredentials($EncryptedUserID, $VerificationKey);
78 function Authenticator(&$Context) {
79 $this->Context
= &$Context;
82 function DeAuthenticate() {
83 $this->Context
->Session
->Destroy();
85 // Destroy the cookies as well
87 $this->Context
->Configuration
['COOKIE_USER_KEY'],
88 $this->Context
->Configuration
['COOKIE_VERIFICATION_KEY']);
89 $UseSsl = ($this->Context
->Configuration
['HTTP_METHOD'] === "https");
90 foreach($Cookies as $Cookie) {
91 // PHP 5.2.0 required for HTTP only parameter of setcookie()
92 if (version_compare(PHP_VERSION
, '5.2.0', '>=')) {
96 $this->Context
->Configuration
['COOKIE_PATH'],
97 $this->Context
->Configuration
['COOKIE_DOMAIN'],
98 $UseSsl, // Secure connections only
104 $this->Context
->Configuration
['COOKIE_PATH'],
105 $this->Context
->Configuration
['COOKIE_DOMAIN'],
106 $UseSsl); // Secure connections only
108 unset($_COOKIE[$Cookie]);
113 function GetIdentity() {
114 $UserID = $this->Context
->Session
->GetVariable(
115 $this->Context
->Configuration
['SESSION_USER_IDENTIFIER'], 'int');
117 // UserID wasn't found in the session, so attempt to retrieve it from the cookies
118 // Retrieve cookie values
119 $EncryptedUserID = ForceIncomingCookieString($this->Context
->Configuration
['COOKIE_USER_KEY'], '');
120 $VerificationKey = ForceIncomingCookieString($this->Context
->Configuration
['COOKIE_VERIFICATION_KEY'], '');
122 if ($EncryptedUserID != '' && $VerificationKey != '') {
124 // Compare against db values
125 // Sadly, because this class is meant to be an interface for distributed objects, I can't use any of the error checking in the Lussumo Framework
126 $Query = "select UserID
128 where VerificationKey = '".FormatStringForDatabaseInput($VerificationKey)."'";
130 $Result = $this->Context
->Database
->Execute($Query,
133 'An error occurred while attempting to validate your remember me credentials');
137 while ($rows = $this->Context
->Database
->GetRow($Result)) {
138 if ($EncryptedUserID == md5($rows['UserID'])) {
139 $UserID = ForceInt($rows['UserID'], 0);
140 $EncryptedUserID = $rows['EncryptedUserID'];
145 // 1. Set a new verification key
146 $VerificationKey = DefineVerificationKey();
148 // 2. Update the user's information
149 $this->UpdateLastVisit($UserID, $VerificationKey);
151 // 3. Set the 'remember me' cookies
152 $this->SetCookieCredentials($EncryptedUserID, $VerificationKey);
154 // 4. Log the user's IP address
155 $this->LogIp($UserID);
161 // If it has now been found, set up the session.
162 $this->AssignSessionUserID($UserID);
166 // All methods below this point are specific to this authenticator and
167 // should not be treated as interface methods. The only required interface
168 // properties and methods appear above.
170 function AssignSessionUserID($UserID) {
172 $this->Context
->Session
->SetVariable(
173 $this->Context
->Configuration
['SESSION_USER_IDENTIFIER'], $UserID);
177 function LogIp($UserID) {
178 if ($this->Context
->Configuration
['LOG_ALL_IPS']) {
179 $Query = "insert into LUM_IpHistory
180 (UserID, RemoteIp, DateLogged)
181 values ('".$UserID."', '".GetRemoteIp(1)."', '".MysqlDateTime()."')";
183 $this->Context
->Database
->Execute($Query,
186 'An error occurred while logging your IP address.',
187 false); // fail silently
191 function SetCookieCredentials($CookieUserID, $VerificationKey) {
192 // Note: 2592000 is 60*60*24*30 or 30 days
194 $this->Context
->Configuration
['COOKIE_USER_KEY'] => $CookieUserID,
195 $this->Context
->Configuration
['COOKIE_VERIFICATION_KEY'] => $VerificationKey);
196 $UseSsl = ($this->Context
->Configuration
['HTTP_METHOD'] === "https");
197 foreach($Cookies as $Name => $Value) {
198 // PHP 5.2.0 required for HTTP only parameter of setcookie()
199 if (version_compare(PHP_VERSION
, '5.2.0', '>=')) {
203 $this->Context
->Configuration
['COOKIE_PATH'],
204 $this->Context
->Configuration
['COOKIE_DOMAIN'],
205 $UseSsl, // Secure connections only
211 $this->Context
->Configuration
['COOKIE_PATH'],
212 $this->Context
->Configuration
['COOKIE_DOMAIN'],
213 $UseSsl); // Secure connections only
218 function UpdateLastVisit($UserID, $VerificationKey) {
219 $Query = "update LUM_User
220 set DateLastActive = '".MysqlDateTime()."',
221 VerificationKey = '".$VerificationKey."',
222 CountVisit = CountVisit + 1
223 where UserID = ".$UserID;
225 $this->Context
->Database
->Execute($Query,
228 'An error occurred while updating your profile.',
229 false); // fail silently