ConcurrentSessionFilter做的功能比較簡單,主要是判斷session是否過期以及更新最新訪問時間
通過代碼HttpSession session = request.getSession(false);判斷獲取session
1、首先判斷session是否存在--------HttpSession session = request.getSession(false)
如果session不存在,直接放過,執行下一個過濾器。
如果存在,則執行第二步
2、根據sessionid從sessionRegistry中獲取SessionInformation,從SessionInformation中獲取session是否過期
如果沒有過期,則更新SessionInformation的訪問日期。
如果過期,則執行doLogout()方法,這個方法會將session無效,並將SecurityContext中的Authentication中的權限置空,同時在SecurityContenxtHoloder中清除SecurityContext
然後查看是否有跳轉的URL,如果有就跳轉,沒有就輸出提示信息
在ConcurrentSessionFilter有兩個重要的類需要知道,一個是sessionRegistry(默認使用sessionRegistryImpl),一個是SessionInformation 。
sessionRegistry顧名思義 session註冊表,有維護兩個類變量ConcurrentMap<Object,Set<String>> principals 和Map<String, SessionInformation> sessionIds
principals以用戶認證信息爲key,values值sessionId集合,sessionIds以sessionId爲key,以SessionInformation 爲values值。
sessionInformation只要存放4個參數,一個是lastRequest;(最近訪問時間),一個是sessionId,一個是principal(用戶認證權限),一個是expired (是否過期)
這兩個類變量的信息會在後面的登陸認證的時候進行賦值
代碼如下
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
if (session != null) {
SessionInformation info = sessionRegistry.getSessionInformation(session.getId());
if (info != null) {
if (info.isExpired()) {
// Expired - abort processing
doLogout(request, response);
String targetUrl = determineExpiredUrl(request, info);
if (targetUrl != null) {
redirectStrategy.sendRedirect(request, response, targetUrl);
return;
} else {
response.getWriter().print("This session has been expired (possibly due to multiple concurrent " +
"logins being attempted as the same user).");
response.flushBuffer();
}
return;
} else {
// Non-expired - update last request date/time
sessionRegistry.refreshLastRequest(info.getSessionId());
}
}
}
chain.doFilter(request, response);
}