Как можно ограничить количество попыток входа в Spring Security? - PullRequest
18 голосов
/ 18 марта 2011

Есть ли в Spring Security какой-либо модуль конфигурации или доступный модуль для ограничения попыток входа в систему (в идеале, я бы хотел увеличить время ожидания между последующими неудачными попытками)? Если нет, какую часть API следует использовать для этого?

Ответы [ 7 ]

14 голосов
/ 18 марта 2011

Реализация AuthenticationFailureHandler, который обновляет счет / время в БД.Я не рассчитывал на использование сеанса, потому что злоумышленник все равно не будет отправлять куки.

12 голосов
/ 09 февраля 2016

От Spring 4.2 и выше доступны прослушиватели событий на основе аннотаций :

@Component
public class AuthenticationEventListener {

    @EventListener
    public void authenticationFailed(AuthenticationFailureBadCredentialsEvent event) {

        String username = (String) event.getAuthentication().getPrincipal();

        // update the failed login count for the user
        // ...
    }

}
5 голосов
/ 26 марта 2013

Как предложено Робом Уинчем в http://forum.springsource.org/showthread.php?108640-Login-attempts-Spring-security, Я просто подклассифицировал DaoAuthenticationProvider (что также можно было бы сделать с использованием аспекта, как предлагает Ритеш), чтобы ограничить количество неудачных входов в систему, но вы также можете утверждать предварительноа также условия:

public class LimitingDaoAuthenticationProvider extends DaoAuthenticationProvider {
  @Autowired
  private UserService userService;
    @Override
    public Authentication authenticate(Authentication authentication)
        throws AuthenticationException {
      // Could assert pre-conditions here, e.g. rate-limiting
      // and throw a custom AuthenticationException if necessary

      try {
        return super.authenticate(authentication);
      } catch (BadCredentialsException e) {
        // Will throw a custom exception if too many failed logins have occurred
        userService.recordLoginFailure(authentication);
        throw e;
      }
   }
}

В XML конфигурации Spring просто ссылайтесь на этот bean-компонент:

<beans id="authenticationProvider"   
    class="mypackage.LimitingDaoAuthenticationProvider"
    p:userDetailsService-ref="userDetailsService"
    p:passwordEncoder-ref="passwordEncoder"/>

<security:authentication-manager>
    <security:authentication-provider ref="authenticationProvider"/>
</security:authentication-manager>

Обратите внимание, что я думаю, что решения, основанные на доступе к AuthenticationException 'authentication или extraInformation свойства (такие как реализация AuthenticationFailureHandler), вероятно, не должны использоваться, потому что эти свойства теперь устарели (по крайней мере, в Spring Security 3.1).

5 голосов
/ 19 марта 2011

Недавно я реализовал аналогичную функцию для отслеживания сбоев входа в систему с помощью JMX. См. Код в моем ответе на вопрос Публикация уведомлений JMX при использовании Spring без NotificationPublisherAware . Аспект метода аутентификации провайдера аутентификации обновляет MBean и работает со слушателем уведомлений (код не показан в этом вопросе), чтобы блокировать пользователя и IP, отправлять оповещения по электронной почте и даже приостанавливать вход в систему, если сбои превышают пороговое значение.

Редактировать
Аналогично моему ответу на вопрос Безопасность Spring 3. Сохранение информации об аутентификации в базе данных , я думаю, что захват события сбоя аутентификации (в отличие от настройки обработчика) и сохранение информации в базе данных также будут работать, и это будет также держите код отделенным.

4 голосов
/ 30 апреля 2014

Вот моя реализация, надеюсь, поможет.

  1. Создать таблицу для хранения любых недопустимых попыток входа в систему.
  2. Если недопустимые попытки> максимально допустимый, установите для UserDetail.accountNonLocked значение false
  3. Spring Security будет обрабатывать «процесс блокировки» для вас. (см. AbstractUserDetailsAuthenticationProvider)

Наконец, расширяет DaoAuthenticationProvider и интегрирует логику внутри.

@Component("authenticationProvider")
public class YourAuthenticationProvider extends DaoAuthenticationProvider {

@Autowired
UserAttemptsDao userAttemptsDao;

@Override
public Authentication authenticate(Authentication authentication) 
      throws AuthenticationException {

  try {

    Authentication auth = super.authenticate(authentication);

    //if corrent password, reset the user_attempts
    userAttemptsDao.resetFailAttempts(authentication.getName());

    return auth;

  } catch (BadCredentialsException e) { 

    //invalid login, update user_attempts, set attempts+1 
    userAttemptsDao.updateFailAttempts(authentication.getName());

    throw e;

  } 

}


}

Для получения полного исходного кода и реализации, пожалуйста, обратитесь к этому - Пример попытки входа в Spring Security limit ,

4 голосов
/ 14 февраля 2014

Вы также можете использовать сервис, который реализует ApplicationListener для обновления записи в БД.

См. События приложения весны.

1 голос
/ 03 ноября 2016
  1. создать таблицу для хранения значений неудачных попыток, например: user_attempts
  2. Запись пользовательского прослушивателя событий

     @Component("authenticationEventListner")
     public class AuthenticationEventListener
     implements AuthenticationEventPublisher
     {
     @Autowired
     UserAttemptsServices userAttemptsService;
    
     @Autowired
     UserService userService;
    
     private static final int MAX_ATTEMPTS = 3;
     static final Logger logger = LoggerFactory.getLogger(AuthenticationEventListener.class);   
    
     @Override
     public void publishAuthenticationSuccess(Authentication authentication) {          
     logger.info("User has been logged in Successfully :" +authentication.getName());       
     userAttemptsService.resetFailAttempts(authentication.getName());       
     }
    
    
     @Override
     public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {               
     logger.info("User Login failed :" +authentication.getName());      
     String username = authentication.getName().toString();
     UserAttempts userAttempt =  userAttemptsService.getUserAttempts(username);
     User userExists = userService.findBySSO(username);
    
     int attempts = 0;
     String error = "";
     String lastAttempted = "";             
     if (userAttempt == null) {     
    
        if(userExists !=null ){                     
        userAttemptsService.insertFailAttempts(username);   }       
      } else {                
          attempts = userAttempt.getAttempts();
          lastAttempted = userAttempt.getLastModified();
        userAttemptsService.updateFailAttempts(username, attempts);         
        if (attempts + 1 >= MAX_ATTEMPTS) {                 
            error = "User account is locked! <br>Username : "
                           + username+ "<br>Last Attempted on : " + lastAttempted;          
        throw new LockedException(error);           
        }                                   
      }
    throw new BadCredentialsException("Invalid User Name and Password");
    
    
    
     }
      }
    

3.ЗащитаКонфигурация

         1) @Autowired
         @Qualifier("authenticationEventListner")
         AuthenticationEventListener authenticationEventListner;

      2) @Bean
         public AuthenticationEventPublisher authenticationListener() {
         return new AuthenticationEventListener();
         }
      3) @Autowired
         public void 
         configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
         auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
         //configuring custom user details service
         auth.authenticationProvider(authenticationProvider);
         // configuring login success and failure event listener
         auth.authenticationEventPublisher(authenticationEventListner);
         }
...