Spring Security中是否有一些配置或可用模块来限制登录尝试(理想情况下,我希望在后续失败尝试之间等待的时间越来越长)?如果没有,API的哪一部分应该用于这个?如何限制Spring Security中的登录尝试?
回答
实现一个AuthenticationFailureHandler,用于更新数据库中的计数/时间。我不会指望使用会话,因为攻击者无论如何都不会发送cookie。
我最近实现了一个类似的功能来监视使用JMX的登录失败。请参阅我对Publish JMX notifications in using Spring without NotificationPublisherAware问题的回答中的代码。身份验证提供程序的身份验证方法的一个方面是更新MBean,并与通知侦听程序(代码未在该问题中显示)一起使用来阻止用户和IP,发送警报电子邮件,甚至在失败超过阈值时挂起登录。
编辑
到我的回答质疑Spring security 3 : Save informations about authentification in database类似,我认为拍摄认证失败事件(而不是定制处理器),并存储在数据库中的信息也将工作,它会保持分离以及代码。
如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 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
或可能不应该使用属性(例如实现AuthenticationFailureHandler
),因为这些属性现在已被弃用(至少在Spring Security 3.1中)。
您也可以使用实现ApplicationListener <AuthenticationFailureBadCredentialsEvent>的服务来更新数据库中的记录。
查看春季应用程序事件。
我发现这种方式比创建自定义身份验证提供程序的其他解决方案更清洁。从spring 4.2开始,这可以通过批注来处理,从而进一步将类与Spring Security框架分离。 – Jberg 2015-07-27 15:38:24
这是我的实施,希望有所帮助。
- 创建一个表来存储任何无效的登录尝试。
- 如果无效次数> max允许,将UserDetail.accountNonLocked设置为false
- 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 login attempts example,
从春天4。2个向上annotation based event listeners可供选择:
@Component
public class AuthenticationEventListener {
@EventListener
public void authenticationFailed(AuthenticationFailureBadCredentialsEvent event) {
String username = (String) event.getAuthentication().getPrincipal();
// update the failed login count for the user
// ...
}
}
- 创建一个表来存储失败的尝试前值: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);
}
无需抛出BadCredentialsException - 它将由事件发布者(例如ProviderManager)抛出。 – isobretatel 2017-05-04 16:57:13
听众方法存在问题:您没有真正锁定用户帐户。下次用户输入有效凭证时,系统应显示错误消息“您的帐户被锁定”,但实际上它将允许成功验证。 – isobretatel 2017-05-04 17:08:40
在侦听器中抛出异常并不是一个好习惯。 – isobretatel 2017-05-05 12:40:23
- 1. Spring Security - 如何在JSP中呈现剩余的登录尝试
- 2. 如何限制登录尝试?
- 3. 限制Openfire登录尝试
- 4. 登录尝试限制
- 5. 限制登录尝试?
- 6. 限制登录尝试保护BFA的
- 7. 限制在Laravel 5.4中自定义登录的登录尝试
- 8. 有限的登录尝试
- 9. 使用Spring Security录制登录
- 10. Facebook登录Spring Security
- 11. Spring Security登录表
- 12. Spring Security Servlet登录
- 13. 限制登录尝试次数
- 14. 限制登录尝试,无论用户?
- 15. Spring Security HTTPS - 尝试使用https登录时出错
- 16. Spring Security以并发登录尝试锁定用户
- 17. 如何在Java webapp中限制登录尝试?
- 18. Spring Security的登录页
- 19. 如何限制使用redis的登录尝试?
- 20. 如何限制laravel 4用户的登录尝试
- 21. 如何限制登录尝试 - PHP&MySQL&CodeIgniter
- 22. Grails + Spring Security单场登录
- 23. Spring Security登录失败
- 24. Spring Security表单登录
- 25. Spring Security Max登录会话
- 26. Spring Security登录问题
- 27. Spring Security登录问题 -
- 28. 登录尝试的PHP登录脚本
- 29. Spring Security中的其他参数登录
- 30. Spring Security中的程序化登录2
不幸的是,由于getAuthentication和getExtraInformation都不再使用AuthenticationException,所以无法从数据库获取用户(不解析HttpServletRequest的参数),因此很难获得Principal(用于其用户名或ID)。使用AuthenticationProvider似乎适用于(下面,类似于Ritesh的建议)。 – paulcm 2013-03-26 18:32:16