默认情况下,当 session(默认30分钟) 失效后会请求回认证页面。我们可以自定义 session 失效后,响应不同的结果。
自定义CustomInvalidSessionStrategy类实现InvalidSessionStrategy
/** * 当session失效后的处理逻辑 */ @Component("customInvalidSessionStrategy") public class CustomInvalidSessionStrategy implements InvalidSessionStrategy { @Override public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException { // 1.将浏览器的sessionid清除,不关闭浏览器cookie不会被删除,一直请求都提示:Session失效 cancelCookie(request, response); //2.当session失效后响应json数据给前端 Result result = new Result().build(HttpStatus.UNAUTHORIZED.value(), "登录超时,请重新登录"); String s = result.toJsonString(); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(s); } protected void cancelCookie(HttpServletRequest request, HttpServletResponse response) { Cookie cookie = new Cookie("JSESSIONID", null); cookie.setMaxAge(0); cookie.setPath(getCookiePath(request)); response.addCookie(cookie); } private String getCookiePath(HttpServletRequest request) { String contextPath = request.getContextPath(); return contextPath.length() > 0 ? contextPath : "/"; } }
在安全配置类SpringSecurityConfig中注入自定义CustomInvalidSessionStrategy实例并进行配置
@Autowired CustomInvalidSessionStrategy customInvalidSessionStrategy; /** * 记住我 功能 */ @Autowired DataSource dataSource; @Bean public JdbcTokenRepositoryImpl jdbcTokenRepository(){ JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl(); jdbcTokenRepository.setDataSource(dataSource); // 是否启动时自动创建表,第一次启动创建就行,后面启动把这个注释掉,不然报错已存在表 //jdbcTokenRepository.setCreateTableOnStartup(true); return jdbcTokenRepository; } /** * 资源权限配置(过滤器链): * 1、被拦截的资源 * 2、资源所对应的角色权限 * 3、定义认证方式:httpBasic 、httpForm * 4、定制登录页面、登录请求地址、错误处理方式 * 5、自定义 spring security 过滤器 * * @param http * @throws Exception */ @Override protected void configure(HttpSecurity http) throws Exception { //http.httpBasic()//采用httpBasic 认证方式 /*http.formLogin() .loginPage("/login/page")// 交给 /login/page 响应认证(登录)页面 .loginProcessingUrl("/login/form") // 登录表单提交处理Url, 默认是 /login .usernameParameter("name") // 默认用户名的属性名是 username .passwordParameter("pwd") // 默认密码的属性名是 password .and() .authorizeRequests()//认证请求 .antMatchers("/login/page").permitAll()//自定义登录页不需要认证 .anyRequest().authenticated();// 所有进入应用的HTTP请求都要进行认证*/ http .addFilterBefore(imageVerifyCodeValidateFilter, UsernamePasswordAuthenticationFilter.class)//将校验过滤器 imageCodeValidateFilter 添加到 UsernamePasswordAuthenticationFilter 前面 .addFilterBefore(smsVerifyCodeValidateFilter,UsernamePasswordAuthenticationFilter.class)//将校验过滤器 smsVerifyCodeValidateFilter 添加到 UsernamePasswordAuthenticationFilter 前面 .formLogin() .loginPage(securityProperties.getLoginPage())// 交给 /login/page 响应认证(登录)页面 .loginProcessingUrl(securityProperties.getLoginProcessingUrl()) // 登录表单提交处理Url, 默认是 /login .usernameParameter(securityProperties.getUsernameParameter()) // 默认用户名的属性名是 username .passwordParameter(securityProperties.getPasswordParameter()) // 默认密码的属性名是 password .successHandler(customAuthenticationSuccessHandler)//自定义认证成功处理器 .failureHandler(customAuthenticationFailureHandler)//自定义认证失败处理器 .and() .authorizeRequests()//认证请求 .antMatchers(securityProperties.getLoginPage(),securityProperties.getMobilePage(),securityProperties.getImageCodeUrl(),securityProperties.getMobileCodeUrl()).permitAll()//自定义登录页不需要认证,生成图片验证码,发送短信获取验证码也不需要验证 .anyRequest().authenticated()// 所有进入应用的HTTP请求都要进行认证 .and() .rememberMe()//记住我功能 .tokenRepository(jdbcTokenRepository())//保存登录信息 .tokenValiditySeconds(securityProperties.getTokenValiditySeconds())//记住我有效时长一周 .and() .sessionManagement()//session会话管理 .invalidSessionStrategy(customInvalidSessionStrategy)//当session失效后的处理类 ; // 将手机相关的配置绑定过滤器链上 http.apply(mobileAuthenticationConfig); }
测试:
完整代码地址:https://gitee.com/zhechaochao/security-parent.git