前面我们讲了 记住我 登录方式,以及和其它登录方式相融合的多种登录形式,想必对 记住我 登录方式有了一个大致清晰的了解。本次我们就来说一下其中一个比较重要的 Filter,即 RememberMeAuthenticationFilter。
RememberMeAuthenticationFilter 是 记住我 登录方式比较重要的类,其主要功能有 自动登录、身份认证、登录成功、事件发布、异常处理/登录失败 等。
另外,重要的一点是,该 Filter 执行有一个条件,就是当前用户尚未认证。
if (SecurityContextHolder.getContext().getAuthentication() == null) {
......
}
下面就这几项重要功能分别加以说明。
当当前用户尚未登录时,先执行 自动登录 逻辑,即先调用 RememberMeServices 的 autoLogin 方法。
Authentication rememberMeAuth = rememberMeServices.autoLogin(request,
response);
如果 rememberMeAuth 不为 null,则再执行身份认证。
rememberMeAuth = authenticationManager.authenticate(rememberMeAuth);
没忘了 AuthenticationManager 吧?前面详细讲过:史上最简单的Spring Security教程(二十七):AuthenticationManager默认实现之ProviderManager详解。
身份认证成功(不发生异常)后,先将当前 Authentication 设置到 SecurityContextHolder 上下文中,然后再执行成功登录逻辑。
// Store to SecurityContextHolder
SecurityContextHolder.getContext().setAuthentication(rememberMeAuth);
onSuccessfulAuthentication(request, response, rememberMeAuth);
之后,便调用时间发布器,发布相关事件。
// Fire event
if (this.eventPublisher != null) {
eventPublisher
.publishEvent(new InteractiveAuthenticationSuccessEvent(
SecurityContextHolder.getContext()
.getAuthentication(), this.getClass()));
}
然后,如果设置了 AuthenticationSuccessHandler ,则调用成功登录逻辑。没忘了 AuthenticationSuccessHandler 的用法吧?之前我们同样也介绍过:史上最简单的Spring Security教程(五):成功登录SuccessHandler高级用法。
此外,如果想跳转到某个特定页面,而不是用户一开始访问的页面,怎么办呢?同样是在 AuthenticationSuccessHandler 中设置 defaultTargetUrl ,之前也详细讲解过,并且也画了一个详细的流程图:史上最简单的Spring Security教程(四):成功登录页面。
接下来,便是异常处理/登录失败了。捕获到身份认证过程中的异常后,进行 异常处理/登录失败 相关处理。
catch (AuthenticationException authenticationException) {
if (logger.isDebugEnabled()) {
logger.debug(
"SecurityContextHolder not populated with remember-me token, as "
+ "AuthenticationManager rejected Authentication returned by RememberMeServices: '"
+ rememberMeAuth
+ "'; invalidating remember-me token",
authenticationException);
}
rememberMeServices.loginFail(request, response);
onUnsuccessfulAuthentication(request, response,
authenticationException);
}
最后,如果不满足该 Filter 触发条件,即当前用户已经身份认证完成或存在其身份认证信息,或者 调用 自动登录 后得不到相应的结果,即 自动登录 失败,便会调用后续的 Filter。
else {
if (logger.isDebugEnabled()) {
logger.debug("SecurityContextHolder not populated with remember-me token, as it already contained: '"
+ SecurityContextHolder.getContext().getAuthentication() + "'");
}
chain.doFilter(request, response);
}
如果想自定义 登录成功 、登录失败(注意不是AuthenticationSuccessHandler、AuthenticationFailureHandler) 怎么办呢?当然是一样的逻辑咯,继承此 Filter 后,实现两个方法即可。
protected void onSuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, Authentication authResult) {
}
......
protected void onUnsuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, AuthenticationException failed) {
}
RememberMeAuthenticationFilter 的主要功能介绍完毕。
其它详细源码,请参考文末源码链接,可自行下载后阅读。
我是银河架构师,十年饮冰,难凉热血,愿历尽千帆,归来仍是少年!
如果文章对您有帮助,请举起您的小手,轻轻【三连】,这将是笔者持续创作的动力源泉。当然,如果文章有错误,或者您有任何的意见或建议,请留言。感谢您的阅读!
源码
github
https://github.com/liuminglei/SpringSecurityLearning/tree/master/36
gitee
https://gitee.com/xbd521/SpringSecurityLearning/tree/master/36