Changeset View
Changeset View
Standalone View
Standalone View
src/applications/auth/provider/PhabricatorPasswordAuthProvider.php
| Show First 20 Lines • Show All 249 Lines • ▼ Show 20 Lines | final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider { | ||||
| public function processLoginRequest( | public function processLoginRequest( | ||||
| PhabricatorAuthLoginController $controller) { | PhabricatorAuthLoginController $controller) { | ||||
| $request = $controller->getRequest(); | $request = $controller->getRequest(); | ||||
| $viewer = $request->getUser(); | $viewer = $request->getUser(); | ||||
| $content_source = PhabricatorContentSource::newFromRequest($request); | $content_source = PhabricatorContentSource::newFromRequest($request); | ||||
| $captcha_limit = 5; | $rate_actor = PhabricatorSystemActionEngine::newActorFromRequest($request); | ||||
| $hard_limit = 32; | |||||
| $limit_window = phutil_units('15 minutes in seconds'); | PhabricatorSystemActionEngine::willTakeAction( | ||||
epriestley: These limits have changed slightly: captcha from "5 per 15 minutes" to "10 per hour", and… | |||||
| array($rate_actor), | |||||
| $failed_attempts = PhabricatorUserLog::loadRecentEventsFromThisIP( | new PhabricatorAuthTryPasswordAction(), | ||||
| PhabricatorUserLog::ACTION_LOGIN_FAILURE, | 1); | ||||
| $limit_window); | |||||
| // If the same remote address has submitted several failed login attempts | // If the same remote address has submitted several failed login attempts | ||||
| // recently, require they provide a CAPTCHA response for new attempts. | // recently, require they provide a CAPTCHA response for new attempts. | ||||
| $require_captcha = false; | $require_captcha = false; | ||||
| $captcha_valid = false; | $captcha_valid = false; | ||||
| if (AphrontFormRecaptchaControl::isRecaptchaEnabled()) { | if (AphrontFormRecaptchaControl::isRecaptchaEnabled()) { | ||||
| if (count($failed_attempts) > $captcha_limit) { | try { | ||||
| PhabricatorSystemActionEngine::willTakeAction( | |||||
| array($rate_actor), | |||||
| new PhabricatorAuthTryPasswordWithoutCAPTCHAAction(), | |||||
| 1); | |||||
| } catch (PhabricatorSystemActionRateLimitException $ex) { | |||||
| $require_captcha = true; | $require_captcha = true; | ||||
| $captcha_valid = AphrontFormRecaptchaControl::processCaptcha($request); | $captcha_valid = AphrontFormRecaptchaControl::processCaptcha($request); | ||||
| } | } | ||||
| } | } | ||||
| // If the user has submitted quite a few failed login attempts recently, | |||||
| // give them a hard limit. | |||||
| if (count($failed_attempts) > $hard_limit) { | |||||
| $guidance = array(); | |||||
| $guidance[] = pht( | |||||
| 'Your remote address has failed too many login attempts recently. '. | |||||
| 'Wait a few minutes before trying again.'); | |||||
| $guidance[] = pht( | |||||
| 'If you are unable to log in to your account, you can '. | |||||
| '[[ /login/email | send a reset link to your email address ]].'); | |||||
| $guidance = implode("\n\n", $guidance); | |||||
| $dialog = $controller->newDialog() | |||||
| ->setTitle(pht('Too Many Login Attempts')) | |||||
| ->appendChild(new PHUIRemarkupView($viewer, $guidance)) | |||||
| ->addCancelButton('/auth/start/', pht('Wait Patiently')); | |||||
| return array(null, $dialog); | |||||
| } | |||||
| $response = null; | $response = null; | ||||
| $account = null; | $account = null; | ||||
| $log_user = null; | $log_user = null; | ||||
| if ($request->isFormPost()) { | if ($request->isFormPost()) { | ||||
| if (!$require_captcha || $captcha_valid) { | if (!$require_captcha || $captcha_valid) { | ||||
| $username_or_email = $request->getStr('username'); | $username_or_email = $request->getStr('username'); | ||||
| if (strlen($username_or_email)) { | if (strlen($username_or_email)) { | ||||
| ▲ Show 20 Lines • Show All 90 Lines • Show Last 20 Lines | |||||
These limits have changed slightly: captcha from "5 per 15 minutes" to "10 per hour", and logins from "32 per 15 minutes" to "100 per hour".