springboot + security 自定义session过期处理方式
2017-12-27 10:26
916 查看
security校验session校验是在ConcurrentSessionFilter,在doFilter方法里可以看到如果session过期会执行方法
先做退出操作,在执行session过期策略,这个策略的初始化是在SessionManagementConfigurer.getExpiredSessionStrategy
所以如果你没有设置默认的策略和expiredUrl
构参里默认的是ResponseBodySessionInformationExpiredStrategy策略,
默认策略里如果session过期,退出后执行的是,就是往response里写了一段话,这不是我们想要的结果,所以这里只有自定义策略,复写onExpiredSessionDetected就可以了
所以这里自定义
这里设置contentType需要注意
如果是
那设置的编码格式就会失败,看源码就会知道
如果先往writer里写入内容,那么this.writer == null就是false,useCharset 就是false,设置的编码就是ISO-8859-1,在客户端接受的中文会乱码。
之后再securityConfig里配置
this.doLogout(request, response); this.sessionInformationExpiredStrategy.onExpiredSessionDetected(new SessionInformationExpiredEvent(info, request, response));
先做退出操作,在执行session过期策略,这个策略的初始化是在SessionManagementConfigurer.getExpiredSessionStrategy
SessionInformationExpiredStrategy getExpiredSessionStrategy() { if(this.expiredSessionStrategy != null) { return this.expiredSessionStrategy; } else if(this.expiredUrl == null) { return null; } else { if(this.expiredSessionStrategy == null) { this.expiredSessionStrategy = new SimpleRedirectSessionInformationExpiredStrategy(this.expiredUrl); } return this.expiredSessionStrategy; } }
所以如果你没有设置默认的策略和expiredUrl
private ConcurrentSessionFilter createConccurencyFilter(H http) { SessionInformationExpiredStrategy expireStrategy = this.getExpiredSessionStrategy(); SessionRegistry sessionRegistry = this.getSessionRegistry(http); return expireStrategy == null?new ConcurrentSessionFilter(sessionRegistry):new ConcurrentSessionFilter(sessionRegistry, expireStrategy); }
构参里默认的是ResponseBodySessionInformationExpiredStrategy策略,
public ConcurrentSessionFilter(SessionRegistry sessionRegistry) { Assert.notNull(sessionRegistry, "SessionRegistry required"); this.sessionRegistry = sessionRegistry; this.sessionInformationExpiredStrategy = new ConcurrentSessionFilter.ResponseBodySessionInformationExpiredStrategy(null); }
默认策略里如果session过期,退出后执行的是,就是往response里写了一段话,这不是我们想要的结果,所以这里只有自定义策略,复写onExpiredSessionDetected就可以了
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException { HttpServletResponse response = event.getResponse(); response.getWriter().print("This session has been expired (possibly due to multiple concurrent logins being attempted as the same user)."); response.flushBuffer(); }
所以这里自定义
@Component public class AjaxSessionInformationExpiredStrategy implements SessionInformationExpiredStrategy { @Override public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException { HttpServletResponse response = event.getResponse(); HttpServletRequest request = event.getRequest(); JSONObject returnObj = new JSONObject(); if (RequestUtils.isAjax(request)) { returnObj.put("status", "0"); } else { returnObj.put("status", "-1"); returnObj.put("message", "非法登录"); } response.setContentType("application/json;charset=UTF-8"); response.getWriter().print(returnObj.toJSONString()); response.flushBuffer(); } }
这里设置contentType需要注意
如果是
response.getWriter().print(returnObj.toJSONString()); response.setContentType("application/json;charset=UTF-8");
那设置的编码格式就会失败,看源码就会知道
public void setContentType(String type) { if(type != null && !this.insideInclude && !this.responseStarted()) { ContentTypeInfo ct = this.servletContext.parseContentType(type); this.contentType = ct.getContentType(); boolean useCharset = false; if(ct.getCharset() != null && this.writer == null && !this.isCommitted()) { this.charset = ct.getCharset(); this.charsetSet = true; useCharset = true; } if(!useCharset && this.charsetSet) { if(ct.getCharset() == null) { this.exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, ct.getHeader() + "; charset=" + this.charset); } else { this.exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, ct.getContentType() + "; charset=" + this.charset); } } else { this.exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, ct.getHeader()); } } }
如果先往writer里写入内容,那么this.writer == null就是false,useCharset 就是false,设置的编码就是ISO-8859-1,在客户端接受的中文会乱码。
之后再securityConfig里配置
http.sessionManagement(). /** * 同一个账号只能在一个地方登陆 */ maximumSessions(1). 4000 /** * 自定义session过期策略,替代默认的{@link ConcurrentSessionFilter.ResponseBodySessionInformationExpiredStrategy}, * 复写onExpiredSessionDetected方法,默认方法只输出异常,没业务逻辑。这里需要返回json */ expiredSessionStrategy(ajaxSessionInformationExpiredStrategy);
相关文章推荐
- 3.Spring Boot + Security初步使用(覆盖配置的两种方式 配置类和XML注入以自定义页面为例)
- Spring Boot自定义错误页面,Whitelabel Error Page处理方式
- Spring Boot自定义错误页面,Whitelabel Error Page处理方式
- spring boot 源码解析14-默认错误页面处理流程, 自定义,及EnableAutoConfigurationImportSelector处理
- springBoot使用Controller读取配置文件两种方式&读取自定义配置方法
- SpringBoot自定义序列化的使用方式--WebMvcConfigurationSupport
- Java中设置Session过期时间(Spring Boot)
- Springboot自定义异常处理
- Spring处理跨域请求(含有SpringBoot方式)
- springboot + security 自定义csrf校验结果
- spring boot框架学习8-【干货】spring boot的web开发(4)-自定义拦截器处理权限
- 详解使用Spring Boot的AOP处理自定义注解
- Spring-boot中读取核心配置文件application和自定义properties配置文件的方式
- spring boot框架学习8-【干货】spring boot的web开发(4)-自定义拦截器处理权限
- spring boot框架学习8-【干货】spring boot的web开发(4)-自定义拦截器处理权限
- springboot thymeleaf 404 自定义处理
- spring boot中的静态资源加载处理方式
- spring boot + mybatis + spring security(自定义登录界面)环境搭建
- springboot搭建项目之日志AOP,支持日志内容可配置控制(黑名单字段不会打印或其他处理方式)
- 【JavaEE】SSH+Spring Security自定义Security的部分处理策略