예제 #1
0
 /**
  * Throws an exception if the current user triggers flood control.
  *
  * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
  */
 protected function contactFloodControl()
 {
     $limit = $this->config('contact.settings')->get('flood.limit');
     $interval = $this->config('contact.settings')->get('flood.interval');
     if (!$this->flood->isAllowed('contact', $limit, $interval)) {
         drupal_set_message($this->t('You cannot send more than %limit messages in @interval. Try again later.', array('%limit' => $limit, '@interval' => format_interval($interval))), 'error');
         throw new AccessDeniedHttpException();
     }
 }
예제 #2
0
 /**
  * {@inheritdoc}
  */
 public function authenticate(Request $request)
 {
     $flood_config = $this->configFactory->get('user.flood');
     $username = $request->headers->get('PHP_AUTH_USER');
     $password = $request->headers->get('PHP_AUTH_PW');
     // Flood protection: this is very similar to the user login form code.
     // @see \Drupal\user\Form\UserLoginForm::validateAuthentication()
     // Do not allow any login from the current user's IP if the limit has been
     // reached. Default is 50 failed attempts allowed in one hour. This is
     // independent of the per-user limit to catch attempts from one IP to log
     // in to many different user accounts.  We have a reasonably high limit
     // since there may be only one apparent IP for all users at an institution.
     if ($this->flood->isAllowed('basic_auth.failed_login_ip', $flood_config->get('ip_limit'), $flood_config->get('ip_window'))) {
         $accounts = $this->entityManager->getStorage('user')->loadByProperties(array('name' => $username, 'status' => 1));
         $account = reset($accounts);
         if ($account) {
             if ($flood_config->get('uid_only')) {
                 // Register flood events based on the uid only, so they apply for any
                 // IP address. This is the most secure option.
                 $identifier = $account->id();
             } else {
                 // The default identifier is a combination of uid and IP address. This
                 // is less secure but more resistant to denial-of-service attacks that
                 // could lock out all users with public user names.
                 $identifier = $account->id() . '-' . $request->getClientIP();
             }
             // Don't allow login if the limit for this user has been reached.
             // Default is to allow 5 failed attempts every 6 hours.
             if ($this->flood->isAllowed('basic_auth.failed_login_user', $flood_config->get('user_limit'), $flood_config->get('user_window'), $identifier)) {
                 $uid = $this->userAuth->authenticate($username, $password);
                 if ($uid) {
                     $this->flood->clear('basic_auth.failed_login_user', $identifier);
                     return $this->entityManager->getStorage('user')->load($uid);
                 } else {
                     // Register a per-user failed login event.
                     $this->flood->register('basic_auth.failed_login_user', $flood_config->get('user_window'), $identifier);
                 }
             }
         }
     }
     // Always register an IP-based failed login event.
     $this->flood->register('basic_auth.failed_login_ip', $flood_config->get('ip_window'));
     return [];
 }
예제 #3
0
 /**
  * {@inheritdoc}
  */
 public function validateForm(array &$form, FormStateInterface $form_state)
 {
     $message = parent::validateForm($form, $form_state);
     // Check if flood control has been activated for sending emails.
     if (!$this->currentUser()->hasPermission('administer contact forms') && (!$message->isPersonal() || !$this->currentUser()->hasPermission('administer users'))) {
         $limit = $this->config('contact.settings')->get('flood.limit');
         $interval = $this->config('contact.settings')->get('flood.interval');
         if (!$this->flood->isAllowed('contact', $limit, $interval)) {
             $form_state->setErrorByName('', $this->t('You cannot send more than %limit messages in @interval. Try again later.', array('%limit' => $limit, '@interval' => $this->dateFormatter->formatInterval($interval))));
         }
     }
     return $message;
 }
 /**
  * Enforces flood control for the current login request.
  *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request.
  * @param string $username
  *   The user name sent for login credentials.
  */
 protected function floodControl(Request $request, $username)
 {
     $flood_config = $this->config('user.flood');
     if (!$this->flood->isAllowed('user.failed_login_ip', $flood_config->get('ip_limit'), $flood_config->get('ip_window'))) {
         throw new AccessDeniedHttpException('Access is blocked because of IP based flood prevention.', NULL, Response::HTTP_TOO_MANY_REQUESTS);
     }
     if ($identifier = $this->getLoginFloodIdentifier($request, $username)) {
         // Don't allow login if the limit for this user has been reached.
         // Default is to allow 5 failed attempts every 6 hours.
         if (!$this->flood->isAllowed('user.http_login', $flood_config->get('user_limit'), $flood_config->get('user_window'), $identifier)) {
             if ($flood_config->get('uid_only')) {
                 $error_message = sprintf('There have been more than %s failed login attempts for this account. It is temporarily blocked. Try again later or request a new password.', $flood_config->get('user_limit'));
             } else {
                 $error_message = 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.';
             }
             throw new AccessDeniedHttpException($error_message, NULL, Response::HTTP_TOO_MANY_REQUESTS);
         }
     }
 }
 /**
  * Checks supplied username/password against local users table.
  *
  * If successful, $form_state->get('uid') is set to the matching user ID.
  */
 public function validateAuthentication(array &$form, FormStateInterface $form_state)
 {
     $password = trim($form_state->getValue('pass'));
     $flood_config = $this->config('user.flood');
     if (!$form_state->isValueEmpty('name') && !empty($password)) {
         // Do not allow any login from the current user's IP if the limit has been
         // reached. Default is 50 failed attempts allowed in one hour. This is
         // independent of the per-user limit to catch attempts from one IP to log
         // in to many different user accounts.  We have a reasonably high limit
         // since there may be only one apparent IP for all users at an institution.
         if (!$this->flood->isAllowed('user.failed_login_ip', $flood_config->get('ip_limit'), $flood_config->get('ip_window'))) {
             $form_state->set('flood_control_triggered', 'ip');
             return;
         }
         $accounts = $this->userStorage->loadByProperties(array('name' => $form_state->getValue('name'), 'status' => 1));
         $account = reset($accounts);
         if ($account) {
             if ($flood_config->get('uid_only')) {
                 // Register flood events based on the uid only, so they apply for any
                 // IP address. This is the most secure option.
                 $identifier = $account->id();
             } else {
                 // The default identifier is a combination of uid and IP address. This
                 // is less secure but more resistant to denial-of-service attacks that
                 // could lock out all users with public user names.
                 $identifier = $account->id() . '-' . $this->getRequest()->getClientIP();
             }
             $form_state->set('flood_control_user_identifier', $identifier);
             // Don't allow login if the limit for this user has been reached.
             // Default is to allow 5 failed attempts every 6 hours.
             if (!$this->flood->isAllowed('user.failed_login_user', $flood_config->get('user_limit'), $flood_config->get('user_window'), $identifier)) {
                 $form_state->set('flood_control_triggered', 'user');
                 return;
             }
         }
         // We are not limited by flood control, so try to authenticate.
         // Store $uid in form state as a flag for self::validateFinal().
         $uid = $this->userAuth->authenticate($form_state->getValue('name'), $password);
         $form_state->set('uid', $uid);
     }
 }