在我的应用程序中,我想为我的用户增加一个失败的登录尝试计数器,并在使用 Spring Security 版本 3.1.4.RELEASE 达到某个尝试计数时锁定他们。
我已经成功实现了一个简单的登录成功通知处理程序,它将计数器重置为零并将此状态保存在我的数据库中,就像这样。
public class BitfoodLoginSuccessHandler extends BitfoodAuthHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest arg0,
HttpServletResponse arg1, Authentication arg2) throws IOException,
ServletException {
String userName = arg2.getName();
AppUser result = getBitfoodDao().getAuthDao().getUser(userName);
if (result.getLoginStatus().getStatus() == UserLoginStatus.STATUS_ACTIVE) {
result.getLoginStatus().setLoginFailCount(0);
getBitfoodDao().getAuthDao().save(result);
} // TODO redirect on success.
}
}
但是,我试图弄清楚如何在失败事件处理程序中实现相反的情况,具体来说,是org.springframework.security.web.authentication.AuthenticationFailureHandler
.
public class BitfoodLoginFailedHandler extends BitfoodAuthHandler implements
AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest arg0,
HttpServletResponse arg1, AuthenticationException arg2)
throws IOException, ServletException {
log.info("???????");
/*if (ls.getLoginFailCount() >= 3) { // TODO parameterize this value
ls.setStatus(UserLoginStatus.STATUS_LOCKED);
}*/
}
}
我知道org.springframework.security.core.AuthenticationException
提供这两种方法可能会提供我需要的登录信息。具体来说,我试图找出当前登录尝试失败的用户名(如果有的话,并且它确实是我在 DB 上的用户)。
org.springframework.security.core.AuthenticationException
AuthenticationException::getAuthentication()
AuthenticationException::getExtraInformation()
但是,在 API 的 3.1.x 版本中,这两种方法都被标记为已弃用。所以:
1)有没有另一种方法可以使用这些通知处理程序检索失败的登录用户名?
2)我应该考虑完全使用另一种机制来执行这个逻辑吗?如果是这样,Spring Security 3 提供了哪些替代方案?
更新:哇,@axtavt 的回答奏效了,结果比我想象的更干净,因为我不再需要弄乱我的安全管理器的过滤器配置了。好的!
更新代码:
我更改了自定义类的接口:
public class BitfoodLoginFailedHandler extends BitfoodAuthHandler
implements ApplicationListener<AuthenticationFailureBadCredentialsEvent>
public class BitfoodLoginSuccessHandler extends BitfoodAuthHandler
implements ApplicationListener<AuthenticationSuccessEvent>
我实施了适当的方法:
public void onApplicationEvent(AuthenticationSuccessEvent event)
public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event)
将它们的 bean 上下文定义保持原样:
<beans:bean id="successHandler" class="org.bitfood.admin.auth.BitfoodLoginSuccessHandler">
<beans:property name="bitfoodDao" ref="daoService"/>
</beans:bean>
<beans:bean id="failureHandler" class="org.bitfood.admin.auth.BitfoodLoginFailedHandler">
<beans:property name="bitfoodDao" ref="daoService"/>
</beans:bean>
瞧!在请求结束之前收到适当的通知(包括用户名数据)。
谢谢!