bug #41137 [Security] Reset limiters on successful login (MatTheCat)

This PR was merged into the 5.2 branch.

Discussion
----------

[Security] Reset limiters on successful login

| Q             | A
| ------------- | ---
| Branch?       | 5.2
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #40890
| License       | MIT
| Doc PR        | N/A

Commits
-------

aa295a48b0 Reset limiters on successful login
This commit is contained in:
Nicolas Grekas 2021-05-10 11:00:08 +02:00
commit 7c43648d93
2 changed files with 15 additions and 5 deletions

View File

@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\Exception\TooManyLoginAttemptsAuthentication
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Event\CheckPassportEvent; use Symfony\Component\Security\Http\Event\CheckPassportEvent;
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
/** /**
* @author Wouter de Jong <wouter@wouterj.nl> * @author Wouter de Jong <wouter@wouterj.nl>
@ -51,10 +52,16 @@ final class LoginThrottlingListener implements EventSubscriberInterface
} }
} }
public function onSuccessfulLogin(LoginSuccessEvent $event): void
{
$this->limiter->reset($event->getRequest());
}
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array
{ {
return [ return [
CheckPassportEvent::class => ['checkPassport', 2080], CheckPassportEvent::class => ['checkPassport', 2080],
LoginSuccessEvent::class => 'onSuccessfulLogin',
]; ];
} }
} }

View File

@ -63,6 +63,12 @@ class LoginThrottlingListenerTest extends TestCase
$this->listener->checkPassport($this->createCheckPassportEvent($passport)); $this->listener->checkPassport($this->createCheckPassportEvent($passport));
} }
$this->listener->onSuccessfulLogin($this->createLoginSuccessfulEvent($passport));
for ($i = 0; $i < 3; ++$i) {
$this->listener->checkPassport($this->createCheckPassportEvent($passport));
}
$this->expectException(TooManyLoginAttemptsAuthenticationException::class); $this->expectException(TooManyLoginAttemptsAuthenticationException::class);
$this->listener->checkPassport($this->createCheckPassportEvent($passport)); $this->listener->checkPassport($this->createCheckPassportEvent($passport));
} }
@ -87,12 +93,9 @@ class LoginThrottlingListenerTest extends TestCase
return new SelfValidatingPassport(new UserBadge($username)); return new SelfValidatingPassport(new UserBadge($username));
} }
private function createLoginSuccessfulEvent($passport, $username = 'wouter') private function createLoginSuccessfulEvent($passport)
{ {
$token = $this->createMock(TokenInterface::class); return new LoginSuccessEvent($this->createMock(AuthenticatorInterface::class), $passport, $this->createMock(TokenInterface::class), $this->requestStack->getCurrentRequest(), null, 'main');
$token->expects($this->any())->method('getUsername')->willReturn($username);
return new LoginSuccessEvent($this->createMock(AuthenticatorInterface::class), $passport, $token, $this->requestStack->getCurrentRequest(), null, 'main');
} }
private function createCheckPassportEvent($passport) private function createCheckPassportEvent($passport)