From 5e9b78b798d1602cb71823c578d23c1bc350b936 Mon Sep 17 00:00:00 2001 From: Andrew Short Date: Fri, 5 Feb 2010 00:36:25 +0000 Subject: [PATCH] FEATURE: Moved the log-in validation process from individual authenticators into Member->checkPassword() and canLogIn(), to allow more extensibility and control (trunk, 2.4). MINOR: Use a ValidationResult to log in a member so that custom errors can be generated. From: Andrew Short git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@98267 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- security/Member.php | 47 ++++++++++++++++++++++++++------ security/MemberAuthenticator.php | 29 ++++++++------------ 2 files changed, 49 insertions(+), 27 deletions(-) mode change 100644 => 100755 security/MemberAuthenticator.php diff --git a/security/Member.php b/security/Member.php index 16680ba91..f02cec610 100755 --- a/security/Member.php +++ b/security/Member.php @@ -129,15 +129,14 @@ class Member extends DataObject { } /** - * Check if the passed password matches the stored one + * Check if the passed password matches the stored one (if the member is not locked out). * - * @param string $password The clear text password to check - * @return bool Returns TRUE if the passed password is valid, otherwise FALSE. + * @param string $password + * @return ValidationResult */ public function checkPassword($password) { - // Only confirm that the password matches if the user isn't locked out - if($this->isLockedOut()) return false; - + $result = $this->canLogIn(); + $spec = Security::encrypt_password( $password, $this->Salt, @@ -145,10 +144,40 @@ class Member extends DataObject { $this ); $e = $spec['encryptor']; - - return $e->compare($this->Password, $spec['password']); + + if(!$e->compare($this->Password, $spec['password'])) { + $result->error(_t ( + 'Member.ERRORWRONGCRED', + 'That doesn\'t seem to be the right e-mail address or password. Please try again.' + )); + } + + return $result; } - + + /** + * Returns a valid {@link ValidationResult} if this member can currently log in, or an invalid + * one with error messages to display if the member is locked out. + * + * You can hook into this with a "canLogIn" method on an attached extension. + * + * @return ValidationResult + */ + public function canLogIn() { + $result = new ValidationResult(); + + if($this->isLockedOut()) { + $result->error(_t ( + 'Member.ERRORLOCKEDOUT', + 'Your account has been temporarily disabled because of too many failed attempts at ' . + 'logging in. Please try again in 20 minutes.' + )); + } + + $this->extend('canLogIn', $result); + return $result; + } + /** * Returns true if this user is locked out */ diff --git a/security/MemberAuthenticator.php b/security/MemberAuthenticator.php old mode 100644 new mode 100755 index f71446cec..f03d4bbd4 --- a/security/MemberAuthenticator.php +++ b/security/MemberAuthenticator.php @@ -32,6 +32,7 @@ class MemberAuthenticator extends Authenticator { public static function authenticate($RAW_data, Form $form = null) { $SQL_user = Convert::raw2sql($RAW_data['Email']); $isLockedOut = false; + $result = null; // Default login (see Security::setDefaultAdmin()) if(Security::check_default_admin($RAW_data['Email'], $RAW_data['Password'])) { @@ -41,9 +42,9 @@ class MemberAuthenticator extends Authenticator { "Member", "\"Email\" = '$SQL_user' AND \"Password\" IS NOT NULL" ); - - if($member && ($member->checkPassword($RAW_data['Password']) == false)) { - if($member->isLockedOut()) $isLockedOut = true; + $result = $member->checkPassword($RAW_data['Password']); + + if($member && !$result->valid()) { $member->registerFailedLogin(); $member = false; } @@ -102,22 +103,14 @@ class MemberAuthenticator extends Authenticator { $member->write(); } - if($member) { - Session::clear("BackURL"); - } else if($isLockedOut) { - if($form) $form->sessionMessage( - _t('Member.ERRORLOCKEDOUT', "Your account has been temporarily disabled because of too many failed attempts at logging in. Please try again in 20 minutes."), - "bad" - ); - } else { - if($form) $form->sessionMessage( - _t('Member.ERRORWRONGCRED', "That doesn't seem to be the right e-mail address or password. Please try again."), - "bad" - ); - } + if($member) { + Session::clear('BackURL'); + } else { + if($form && $result) $form->sessionMessage($result->message(), 'bad'); + } - return $member; - } + return $member; + } /**