目錄
session逾時處理
session并發控制
如果要進行其他的一些特殊處理,比如判斷是誰擠掉了上一個session,在@configuration中
如果要保證第一個浏覽器登入,不讓其他浏覽器登入
session叢集管理
session逾時處理
在配置檔案加上時間
//機關是秒,預設是30分鐘
server.session.timeout = 10
配置了上面的沒有生效,我們檢視源碼的,找到TomcatEmbeddedServletContainerFactory
private void configureSession(Context context) {
long sessionTimeout = this.getSessionTimeoutInMinutes();
context.setSessionTimeout((int)sessionTimeout);
if (this.isPersistSession()) {
Manager manager = context.getManager();
if (manager == null) {
manager = new StandardManager();
context.setManager((Manager)manager);
}
this.configurePersistSession((Manager)manager);
} else {
context.addLifecycleListener(new
TomcatEmbeddedServletContainerFactory.DisablePersistSessionListener());
}
}
private long getSessionTimeoutInMinutes() {
long sessionTimeout = (long)this.getSessionTimeout();
if (sessionTimeout > 0L) {
//秒數轉換成分鐘,傳回的是最小分鐘數字,6s會變成1分鐘
sessionTimeout = Math.max(TimeUnit.SECONDS.toMinutes(sessionTimeout), 1L);
}
return sessionTimeout;
}
在@configuration,SpringSecurity配置中加上
.and()
.sessionManagement()
//session失效的時候,跳轉的位址
.invalidSessionUrl("/session/invalid")
.and()
session失效之後跳轉
@GetMapping("/session/invalid")
@ResponseStatus(code = HttpStatus.UNAUTHORIZED)
public SimpleResponse valid(){
return new SimpleResponse("session失效了");
}
session并發控制
常見場景:一個使用者隻能有一個session,使用者在另一個地方登陸的時候,把其他地方的session失效掉
設定session失效時間和最大session數
//機關是秒,預設是30分鐘
server.session.timeout = 600
//session失效的時候,跳轉的位址
.and()
.sessionManagement()
.invalidSessionUrl("/session/invalid")
//最大session線上數,可以通過配置檔案加載
.maximumSessions(1)
.and()
如果要進行其他的一些特殊處理,比如判斷是誰擠掉了上一個session,在@configuration中
//session失效的時候,跳轉的位址
.sessionManagement()
.invalidSessionUrl("/session/invalid")
.maximumSessions(1)
//imoocExpiredSessionStrategy 中包含session過期之後,跳轉到的頁面
.expiredSessionStrategy(imoocExpiredSessionStrategy )
建立SessionInformationExpiredStrategy類
public class ImoocExpiredSessionStrategy extends AbstractSessionStrategy implements SessionInformationExpiredStrategy {
public ImoocExpiredSessionStrategy(String invalidSessionUrl) {
super(invalidSessionUrl);
}
/* (non-Javadoc)
* @see org.springframework.security.web.session.SessionInformationExpiredStrategy#onExpiredSessionDetected(org.springframework.security.web.session.SessionInformationExpiredEvent)
*/
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
//調用抽象方法,session失效
onSessionInvalid(event.getRequest(), event.getResponse());
}
/* (non-Javadoc)
* @see com.imooc.security.browser.session.AbstractSessionStrategy#isConcurrency()
*/
@Override
protected boolean isConcurrency() {
return true;
}
}
AbstractSessionStrategy
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)'");
Assert.isTrue(StringUtils.endsWithIgnoreCase(invalidSessionUrl, ".html"), "url must end with '.html'");
this.destinationUrl = invalidSessionUrl;
}
/*
* (non-Javadoc)
*
* @see org.springframework.security.web.session.InvalidSessionStrategy#
* onInvalidSessionDetected(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
protected void onSessionInvalid(HttpServletRequest request, HttpServletResponse response) throws IOException {
logger.info("session失效");
if (createNewSession) {
request.getSession();
}
String sourceUrl = request.getRequestURI();
String targetUrl;
if (StringUtils.endsWithIgnoreCase(sourceUrl, ".html")) {
targetUrl = destinationUrl;
logger.info("跳轉到:"+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;
}
/**
* Determines whether a new session should be created before redirecting (to
* avoid possible looping issues where the same session ID is sent with the
* redirected request). Alternatively, ensure that the configured URL does
* not pass through the {@code SessionManagementFilter}.
*
* @param createNewSession
* defaults to {@code true}.
*/
public void setCreateNewSession(boolean createNewSession) {
this.createNewSession = createNewSession;
}
}
AbstractSessionStrategy
這個時候,啟動兩個浏覽器,隻能有一個浏覽器登入成功
如果要保證第一個浏覽器登入,不讓其他浏覽器登入
在@configuration加上配置
.and()
.sessionManagement()
//session失效的時候,跳轉的位址
.invalidSessionUrl("/session/invalid")
.maximumSessions(1)
.invalidSessionStrategy(invalidSessionStrategy)
.maximumSessions(1)
//當session達到maximumSessions,阻止後來的session登入
.maxSessionsPreventsLogin(true)
.expiredSessionStrategy(sessionInformationExpiredStrategy)
.and()