BUG Fix BasicAuth not resetting failed login counts on authentication

This commit is contained in:
Damian Mooyman 2014-10-24 13:43:39 +13:00
parent 6683f3d283
commit 9d78eb7fe6
4 changed files with 58 additions and 20 deletions

View File

@ -463,9 +463,7 @@ class Member extends DataObject implements TemplateGlobalProvider {
}
// Clear the incorrect log-in count
if(self::config()->lock_out_after_incorrect_logins) {
$this->FailedLoginCount = 0;
}
$this->registerSuccessfulLogin();
// Don't set column if its not built yet (the login might be precursor to a /dev/build...)
if(array_key_exists('LockedOutUntil', DB::fieldList('Member'))) {
@ -1560,6 +1558,17 @@ class Member extends DataObject implements TemplateGlobalProvider {
}
}
}
/**
* Tell this member that a successful login has been made
*/
public function registerSuccessfulLogin() {
if(self::config()->lock_out_after_incorrect_logins) {
// Forgive all past login failures
$this->FailedLoginCount = 0;
$this->write();
}
}
/**
* Get the HtmlEditorConfig for this user to be used in the CMS.

View File

@ -73,6 +73,8 @@ class MemberAuthenticator extends Authenticator {
if(!$success) {
if($member) $member->registerFailedLogin();
if($form) $form->sessionMessage($result->message(), 'bad');
} else {
if($member) $member->registerSuccessfulLogin();
}
return $member;

View File

@ -14,15 +14,14 @@ class BasicAuthTest extends FunctionalTest {
parent::setUp();
// Fixtures assume Email is the field used to identify the log in identity
self::$original_unique_identifier_field = Member::config()->unique_identifier_field;
Config::nest();
Member::config()->unique_identifier_field = 'Email';
Member::config()->lock_out_after_incorrect_logins = 10;
}
public function tearDown() {
Config::unnest();
parent::tearDown();
BasicAuth::protect_entire_site(false);
Member::config()->unique_identifier_field = self::$original_unique_identifier_field;
}
public function testBasicAuthEnabledWithoutLogin() {
@ -104,7 +103,31 @@ class BasicAuthTest extends FunctionalTest {
$_SERVER['PHP_AUTH_USER'] = $origUser;
$_SERVER['PHP_AUTH_PW'] = $origPw;
}
public function testBasicAuthFailureIncreasesFailedLoginCount() {
// Prior to login
$check = Member::get()->filter('Email', 'failedlogin@test.com')->first();
$this->assertEquals(0, $check->FailedLoginCount);
// First failed attempt
$_SERVER['PHP_AUTH_USER'] = 'failedlogin@test.com';
$_SERVER['PHP_AUTH_PW'] = 'test';
$response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission');
$check = Member::get()->filter('Email', 'failedlogin@test.com')->first();
$this->assertEquals(1, $check->FailedLoginCount);
// Second failed attempt
$_SERVER['PHP_AUTH_PW'] = 'testwrong';
$response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission');
$check = Member::get()->filter('Email', 'failedlogin@test.com')->first();
$this->assertEquals(2, $check->FailedLoginCount);
// successful basic auth should reset failed login count
$_SERVER['PHP_AUTH_PW'] = 'Password';
$response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission');
$check = Member::get()->filter('Email', 'failedlogin@test.com')->first();
$this->assertEquals(0, $check->FailedLoginCount);
}
}
class BasicAuthTest_ControllerSecuredWithPermission extends Controller implements TestOnly {

View File

@ -1,15 +1,19 @@
Group:
mygroup:
Code: mygroup
mygroup:
Code: mygroup
Member:
user-in-mygroup:
Email: user-in-mygroup@test.com
Password: test
Groups: =>Group.mygroup
user-without-groups:
Email: user-without-groups@test.com
Password: test
user-in-mygroup:
Email: user-in-mygroup@test.com
Password: test
Groups: =>Group.mygroup
user-without-groups:
Email: user-without-groups@test.com
Password: test
failed-login:
Email: failedlogin@test.com
Password: Password
FailedLoginCount: 0
Permission:
mycode:
Code: MYCODE
Group: =>Group.mygroup
mycode:
Code: MYCODE
Group: =>Group.mygroup