Session管理
本文主要描述在 Spring Security
下 Session
的以下三种管理,
Session
超时时间Session
的并发策略- 集群环境
Session
处理
Session超时
application.yml
配置超时时间
server:
port: 80
session:
timeout: 60
http.
......
.sessionManagement()
.invalidSessionUrl("/session/invalid")//session失效跳转的链接
.....
BrowserSecurityController
中/session/invalid
@GetMapping("/session/invalid")
@ResponseStatus(code = HttpStatus.UNAUTHORIZED)
public Result<String> sessionInvalid() {
return ResultUtil.error(HttpStatus.UNAUTHORIZED.value(), "session失效");
}
Session的并发策略
http.
......
.maximumSessions(1)//最大session并发数量1
.maxSessionsPreventsLogin(false)//false之后登录踢掉之前登录,true则不允许之后登录
.expiredSessionStrategy(new MerryyounExpiredSessionStrategy())//登录被踢掉时的自定义操作
.....
MerryyounExpiredSessionStrategy
@Slf4j
public class MerryyounExpiredSessionStrategy implements SessionInformationExpiredStrategy {
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent eventØ) throws IOException, ServletException {
eventØ.getResponse().setContentType("application/json;charset=UTF-8");
eventØ.getResponse().getWriter().write("并发登录!");
}
}
代码重构:将可配置的变量抽取到SessionProperties和SecurityConstants中:
public class SessionProperties {
/**
* 同一个用户在系统中的最大session数,默认1
*/
private int maximumSessions = 1;
/**
* 达到最大session时是否阻止新的登录请求,默认为false,不阻止,新的登录会将老的登录失效掉
*/
private boolean maxSessionsPreventsLogin;
/**
* session失效时跳转的地址
*/
private String sessionInvalidUrl = SecurityConstants.DEFAULT_SESSION_INVALID_URL;
public int getMaximumSessions() {
return maximumSessions;
}
public void setMaximumSessions(int maximumSessions) {
this.maximumSessions = maximumSessions;
}
public boolean isMaxSessionsPreventsLogin() {
return maxSessionsPreventsLogin;
}
public void setMaxSessionsPreventsLogin(boolean maxSessionsPreventsLogin) {
this.maxSessionsPreventsLogin = maxSessionsPreventsLogin;
}
public String getSessionInvalidUrl() {
return sessionInvalidUrl;
}
public void setSessionInvalidUrl(String sessionInvalidUrl) {
this.sessionInvalidUrl = sessionInvalidUrl;
}
}
在SecurityConstants增加:
/**
* session失效默认的跳转地址
*/
public static final String DEFAULT_SESSION_INVALID_URL = "/session/invalid";
下面的三个类是处理session失效以及并发登录的自定义的操作:
public class AbstractSessionStrategy {
private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* 跳转的url
*/
private String destinationUrl;
/**
* 重定向策略
*/
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
/**
* 跳转前是否创建新的session
*/
private boolean createNewSession = true;
private ObjectMapper objectMapper = new ObjectMapper();
/**
* @param invalidSessionUrl
* @param invalidSessionHtmlUrl
*/
public AbstractSessionStrategy(String invalidSessionUrl) {
Assert.isTrue(UrlUtils.isValidRedirectUrl(invalidSessionUrl), "url must start with '/' or with 'http(s)'");
this.destinationUrl = invalidSessionUrl;
}
protected void onSessionInvalid(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (createNewSession) {
request.getSession();
}
String sourceUrl = request.getRequestURI();
String targetUrl;
if (StringUtils.endsWithIgnoreCase(sourceUrl, ".html")) {
targetUrl = destinationUrl+".html";
logger.info("session失效,跳转到"+targetUrl);
redirectStrategy.sendRedirect(request, response, targetUrl);
}else{
Object result = buildResponseContent(request);
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(objectMapper.writeValueAsString(result));
}
}
/**
* @param request
* @return
*/
protected Object buildResponseContent(HttpServletRequest request) {
String message = "session已失效";
if(isConcurrency()){
message = message + ",有可能是并发登录导致的";
}
return new SimpleResponse(message);
}
/**
* session失效是否是并发导致的
* @return
*/
protected boolean isConcurrency() {
return false;
}
public void setCreateNewSession(boolean createNewSession) {
this.createNewSession = createNewSession;
}
}
session失效的配置处理类:
/**
* session失效时的跳转
* @author zhailiang
*
*/
public class ImoocExpiredSessionStrategy extends AbstractSessionStrategy implements SessionInformationExpiredStrategy {
public ImoocExpiredSessionStrategy(String invalidSessionUrl) {
super(invalidSessionUrl);
}
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
onSessionInvalid(event.getRequest(), event.getResponse());
}
@Override
protected boolean isConcurrency() {
return true;
}
}
/**
* 并发登录的自定义处理
* @author zhailiang
*
*/
public class ImoocInvalidSessionStrategy extends AbstractSessionStrategy implements InvalidSessionStrategy {
public ImoocInvalidSessionStrategy(String invalidSessionUrl) {
super(invalidSessionUrl);
}
@Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
onSessionInvalid(request, response);
}
}
说明:本系列博客是记录慕课网中的教程的学习,以便我自己复习回忆。文中涉及的一些细节问题请参考慕课网中相关视频。
贴出慕课网视频教程地址: http://coding.imooc.com/class/134.html