个人网站策划书模板,wordpress用网站测速,做微信商城网站公司,广州海珠区有什么大学security/day08 这个功能大家还熟悉么#xff1f;我们在登录网站的时候#xff0c;除了让你输入用户名和密码#xff0c;还会有个勾选框#xff1a; 记住我#xff01;#xff01;#xff01;不是让大家记住我哈。 值得一提的是#xff0c;Spring Security 也提供了这个… security/day08 这个功能大家还熟悉么我们在登录网站的时候除了让你输入用户名和密码还会有个勾选框 记住我不是让大家记住我哈。 值得一提的是Spring Security 也提供了这个功能我们今天就来体验一把。
代码实战
其实想要开启rememberMe功能其实很简单只需要简单的修改下配置即可 Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests().anyRequest().authenticated().and().formLogin().permitAll().and().rememberMe().and().csrf().disable();return http.build();}实现思路
当用户登录网站后并且勾选rememberMe服务端认证通过则把用户信息进行算法加密加密完成后通过cookie让浏览器把cookie保存在本地当浏览器关闭后重新打开网站浏览器会把cookie带给服务端服务端校验cookie确定用户身份进而自动登录
源码分析
首先我们找切入点我们前面讲过当引入一个新功能的时候必定会引入一个configurer,rememberMe 也不例外点击.rememberMe()进入源码
看到了RememberMeConfigurer我们点进去看下主要是看init和configure方法
init public void init(H http) throws Exception {validateInput();String key getKey();RememberMeServices rememberMeServices getRememberMeServices(http, key);http.setSharedObject(RememberMeServices.class, rememberMeServices);LogoutConfigurerH logoutConfigurer http.getConfigurer(LogoutConfigurer.class);if (logoutConfigurer ! null this.logoutHandler ! null) {logoutConfigurer.addLogoutHandler(this.logoutHandler);}RememberMeAuthenticationProvider authenticationProvider new RememberMeAuthenticationProvider(key);authenticationProvider postProcess(authenticationProvider);http.authenticationProvider(authenticationProvider);initDefaultLoginFilter(http);}getKey() 这个就是我们刚开始设置的key如果不配置每次系统都会重启导致需要重新登录getRememberMeServices() 用来实现自动登录、处理登录成功和登录失败的逻辑主要有两个继承 PersistentTokenBasedRememberMeServices 持久化令牌到数据库TokenBasedRememberMeServices http.authenticationProvider(authenticationProvider);创建一个认证器放到providerList里面initDefaultLoginFilter(http); 在自定生成登录页面加上rememberMe 选框
configure public void configure(H http) {RememberMeAuthenticationFilter rememberMeFilter new RememberMeAuthenticationFilter(http.getSharedObject(AuthenticationManager.class), this.rememberMeServices);if (this.authenticationSuccessHandler ! null) {rememberMeFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);}rememberMeFilter postProcess(rememberMeFilter);http.addFilter(rememberMeFilter);}创建了一个过滤器RememberMeAuthenticationFilterpostProcess(rememberMeFilter); 注入IOC容器在http中加入rememberMe过滤器
看完了RememberMeConfigurer的两个核心方法之后我们现在知道容器中已经有了RememberMeAuthenticationFilter和RememberMeAuthenticationProvider 现在分别来看下
RememberMeAuthenticationFilter
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws IOException, ServletException {Authentication rememberMeAuth this.rememberMeServices.autoLogin(request, response);if (rememberMeAuth ! null) {// Attempt authenticaton via AuthenticationManagertry {rememberMeAuth this.authenticationManager.authenticate(rememberMeAuth);// Store to SecurityContextHolderSecurityContext context SecurityContextHolder.createEmptyContext();context.setAuthentication(rememberMeAuth);SecurityContextHolder.setContext(context);onSuccessfulAuthentication(request, response, rememberMeAuth);this.securityContextRepository.saveContext(context, request, response);if (this.successHandler ! null) {this.successHandler.onAuthenticationSuccess(request, response, rememberMeAuth);return;}}catch (AuthenticationException ex) {this.rememberMeServices.loginFail(request, response);onUnsuccessfulAuthentication(request, response, ex);}}chain.doFilter(request, response);}调用autoLogin方法 从cookie提取用户身份在调用loadUserByUsername获取用户详细信息校验用户身份是否合法(根据不同的令牌存储方式进行不同校验)如果校验通过则返回Authentication(RememberMeAuthenticationToken) authenticate 如果autoLogin成功则和前面普通登录一样进行认证因为这里生成的是RememberMeAuthenticationToken则最终会被RememberMeAuthenticationProvider处理 如果认证返回则进行对应的响应处理
RememberMeAuthenticationProvider public Authentication authenticate(Authentication authentication) throws AuthenticationException {if (!supports(authentication.getClass())) {return null;}if (this.key.hashCode() ! ((RememberMeAuthenticationToken) authentication).getKeyHash()) {throw new BadCredentialsException(this.messages.getMessage(RememberMeAuthenticationProvider.incorrectKey,The presented RememberMeAuthenticationToken does not contain the expected key));}return authentication;}这里的逻辑只做了一步校验key的hashCode是否一致如果一致则校验通过