Существует ли какая-либо конфигурация или доступный модуль в Spring Security для ограничения попыток входа (в идеале, я хотел бы увеличить время ожидания между последующими неудачными попытками)? Если нет, какую часть API следует использовать для этого?
Как я могу ограничить попытки входа в систему Spring Безопасность?
Ответ 1
Внедрить AuthenticationFailureHandler, который обновляет счет/время в БД. Я бы не стал рассчитывать на использование сеанса, потому что злоумышленник все равно не будет отправлять файлы cookie.
Ответ 2
От 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
// ...
}
}
Ответ 3
Как предложил Роб Винч в http://forum.springsource.org/showthread.php?108640-Login-attempts-Spring-security, я просто подклассифицировал DaoAuthenticationProvider
(который также мог быть выполнен с использованием аспекта как Ritesh предлагает) ограничить количество неудачных логинов, но вы также можете утверждать и предварительные условия:
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;
}
}
}
В Spring config XML просто укажите этот 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 Безопасность 3.1, по крайней мере).
Ответ 4
Недавно я реализовал аналогичную функцию для мониторинга сбоев входа в систему с использованием JMX. Пожалуйста, см. Код в ответе на вопрос Опубликовать уведомления JMX при использовании Spring без NotificationPublisherAware. Аспект метода аутентификации поставщика проверки подлинности обновляет MBean и работает с прослушивателем уведомлений (код, который не показан в этом вопросе) для блокировки пользователя и IP-адреса, отправки предупреждающих сообщений и даже приостановки регистрации, если ошибки превышают пороговое значение.
Edit
Как и мой ответ на вопрос Spring безопасность 3: сохраните информацию об аутентификации в базе данных, я думаю, что захват события сбоя аутентификации (в отличие от настройки обработчика) и сохранение информации в базе данных также будет работать, и он также сохранит код.
Ответ 5
Вы также можете использовать службу, которая реализует ApplicationListener <AuthenticationFailureBadCredentialsEvent> для обновления записи в БД.
Смотрите события приложения spring.
Ответ 6
Вот моя реализация, надеюсь, помощь.
- Создайте таблицу для хранения любых недопустимых попыток входа в систему.
- Если недопустимые попытки > max разрешены, установите для параметра UserDetail.accountNonLocked значение false
- Spring Безопасность будет обрабатывать процесс блокировки. (см.
AbstractUserDetailsAuthenticationProvider
)
Last, расширяет 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 Пример попыток входа в лимит безопасности,
Ответ 7
- создать таблицу для хранения значений неудачных попыток ex: user_attempts
-
Запись пользовательского прослушивателя событий
@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.Security
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);
}