默認情況下,當 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