源于官方最新5.7.2文档,若你觉得官方文档阅读起来很枯燥,内容复杂,我提供了解析概括在每个部分的结尾,我对官方文档的内容做了一些改变,实例代码我会在后续进行更新,请查看如:SpringSecurity系列——认证架构实例代码的文章
但是如果你有能力,还是推荐直接阅读官方文档
记住我或持久登录身份验证是指网站能够记住会话之间主体的身份。 这通常是通过向浏览器发送 cookie 来完成的,该 cookie 在未来的会话中被检测到并导致自动登录发生。 Spring Security 为这些操作的发生提供了必要的钩子,并且有两个具体的 remember-me 实现。 一种使用散列来保护基于 cookie 的令牌的安全性,另一种使用数据库或其他持久存储机制来存储生成的令牌。
请注意,这两种实现都需要一个 UserDetailsService. 如果您使用的身份验证提供程序不使用 UserDetailsService(例如,LDAP 提供程序)那么它将无法工作,除非您也有 UserDetailsService bean 在您的应用程序上下文中
这种方法使用散列来实现有用的记住我的策略。 本质上,在交互式身份验证成功后会向浏览器发送一个 cookie,该 cookie 的组成如下
base64(username + ":" + expirationTime + ":" +
md5Hex(username + ":" + expirationTime + ":" password + ":" + key))
username: As identifiable to the UserDetailsService
password: That matches the one in the retrieved UserDetails
expirationTime: The date and time when the remember-me token expires, expressed in milliseconds
key: A private key to prevent modification of the remember-me token
因此,remember-me 令牌仅在指定的时间段内有效,前提是用户名、密码和密钥不更改。 值得注意的是,这有一个潜在的安全问题,即在令牌过期之前,任何用户代理都可以使用捕获的记住我令牌。 这与摘要式身份验证的问题相同。 如果委托人知道令牌已被捕获,他们可以轻松更改密码并立即使所有已发布的记住我令牌无效。 如果需要更重要的安全性,您应该使用下一节中描述的方法。 或者,根本不应该使用记住我的服务。
当前多数项目中并不建议采用这种方法
记住我与 UsernamePasswordAuthenticationFilter 一起使用,并通过 AbstractAuthenticationProcessingFilter 超类中的钩子实现。 它也在 BasicAuthenticationFilter 中使用。 这些钩子将在适当的时候调用一个具体的 RememberMeServices。 如下所示:
Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
void loginFail(HttpServletRequest request, HttpServletResponse response);
void loginSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication successfulAuthentication);
请注意 AbstractAuthenticationProcessingFilter 仅调用 loginFail() 和 loginSuccess() 方法。 每当 SecurityContextHolder 不包含 Authentication 时,都会由 RememberMeAuthenticationFilter 调用 autoLogin() 方法。 因此,该接口为底层的 remember-me 实现提供了足够的身份验证相关事件通知,并在候选 Web 请求可能包含 cookie 并希望被记住时委托给实现。 这种设计允许任意数量的记住我的实现策略。 我们在上面已经看到 Spring Security 提供了两种实现
此实现支持 Simple Hash-Based Token Approach 中描述的更简单的方法。 TokenBasedRememberMeServices 生成一个RememberMeAuthenticationToken,由RememberMeAuthenticationProvider 处理。 此身份验证提供程序和 TokenBasedRememberMeServices 之间共享一个密钥。 此外,TokenBasedRememberMeServices 需要一个 UserDetailsService,它可以从中检索用户名和密码以进行签名比较,并生成 RememberMeAuthenticationToken 以包含正确的 GrantedAuthoritys。 如果用户请求,应用程序应提供某种注销命令,使 cookie 无效。 TokenBasedRememberMeServices 还实现了 Spring Security 的 LogoutHandler 接口,因此可以与 LogoutFilter 一起使用以自动清除 cookie。
应用程序上下文中启用记住我服务所需的 bean 如下:
<bean id="rememberMeFilter" class=
"org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationManager" ref="theAuthenticationManager" />
</bean>
<bean id="rememberMeServices" class=
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="springRocks"/>
</bean>
<bean id="rememberMeAuthenticationProvider" class=
"org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="springRocks"/>
</bean>
不要忘记将 RememberMeServices 实现添加到 UsernamePasswordAuthenticationFilter.setRememberMeServices() 属性中,将 RememberMeAuthenticationProvider 包含在 AuthenticationManager.setProviders() 列表中,并将 RememberMeAuthenticationFilter 添加到 FilterChainProxy(通常紧跟在 UsernamePasswordAuthenticationFilter 之后)。