默认情况下,当 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

posted on 2021-01-24 01:11  西门夜说  阅读(1943)  评论(0编辑  收藏  举报