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 // Clear the incorrect log-in count
if(self::config()->lock_out_after_incorrect_logins) { $this->registerSuccessfulLogin();
$this->FailedLoginCount = 0;
}
// Don't set column if its not built yet (the login might be precursor to a /dev/build...) // 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'))) { 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. * 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(!$success) {
if($member) $member->registerFailedLogin(); if($member) $member->registerFailedLogin();
if($form) $form->sessionMessage($result->message(), 'bad'); if($form) $form->sessionMessage($result->message(), 'bad');
} else {
if($member) $member->registerSuccessfulLogin();
} }
return $member; return $member;

View File

@ -14,15 +14,14 @@ class BasicAuthTest extends FunctionalTest {
parent::setUp(); parent::setUp();
// Fixtures assume Email is the field used to identify the log in identity // 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()->unique_identifier_field = 'Email';
Member::config()->lock_out_after_incorrect_logins = 10;
} }
public function tearDown() { public function tearDown() {
Config::unnest();
parent::tearDown(); parent::tearDown();
BasicAuth::protect_entire_site(false);
Member::config()->unique_identifier_field = self::$original_unique_identifier_field;
} }
public function testBasicAuthEnabledWithoutLogin() { public function testBasicAuthEnabledWithoutLogin() {
@ -104,7 +103,31 @@ class BasicAuthTest extends FunctionalTest {
$_SERVER['PHP_AUTH_USER'] = $origUser; $_SERVER['PHP_AUTH_USER'] = $origUser;
$_SERVER['PHP_AUTH_PW'] = $origPw; $_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 { class BasicAuthTest_ControllerSecuredWithPermission extends Controller implements TestOnly {

View File

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