Shiro DefaultWebSessionManager的设计概念
默认的web应用Session管理器,主要是涉及到Session和Cookie
具备了SessionIdCookie、SessionIdCookie启用开关
涉及到的行为:添加、删除SessionId到Cookie、读取Cookie获得SessionId
构造器
public DefaultWebSessionManager() { // Cookie模板,支持Set注入,用户可以自定义模板 Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
// 提升Cookie安全性,防止XSS攻击 cookie.setHttpOnly(true); this.sessionIdCookie = cookie;
// SessionIdCookie启用开关 this.sessionIdCookieEnabled = true; this.sessionIdUrlRewritingEnabled = true; }
用户自定义Cookie模板
<bean id="shiroCookieTemplate" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg name="name" value="JSESESSIONIDCOOKIE" />
<property name="path" value="/" />
<property name="httpOnly" value="true" />
</bean>
使用模板创建Cookie
Cookie template = getSessionIdCookie(); Cookie cookie = new SimpleCookie(template); public SimpleCookie(Cookie cookie) { this.name = cookie.getName(); this.value = cookie.getValue(); this.comment = cookie.getComment(); this.domain = cookie.getDomain(); this.path = cookie.getPath(); this.maxAge = Math.max(DEFAULT_MAX_AGE, cookie.getMaxAge()); this.version = Math.max(DEFAULT_VERSION, cookie.getVersion()); this.secure = cookie.isSecure(); this.httpOnly = cookie.isHttpOnly(); }
Session创建的过程中
protected void onStart(Session session, SessionContext context) { super.onStart(session, context); if (!WebUtils.isHttp(context)) { log.debug("SessionContext argument is not HTTP compatible or does not have an HTTP request/response " + "pair. No session ID cookie will be set."); return; } HttpServletRequest request = WebUtils.getHttpRequest(context); HttpServletResponse response = WebUtils.getHttpResponse(context); // 判断是否开启了SessionIdCookie if (isSessionIdCookieEnabled()) { Serializable sessionId = session.getId(); // 将SessionId存储到Cookie中 storeSessionId(sessionId, request, response); } else { log.debug("Session ID cookie is disabled. No cookie has been set for new session with id {}", session.getId()); } request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE); }
private void storeSessionId(Serializable currentId, HttpServletRequest request, HttpServletResponse response) { if (currentId == null) { String msg = "sessionId cannot be null when persisting for subsequent requests."; throw new IllegalArgumentException(msg); } Cookie template = getSessionIdCookie(); Cookie cookie = new SimpleCookie(template); String idString = currentId.toString(); cookie.setValue(idString); // 给浏览器添加Cookie:response.addHeader("Set-Cookie", "JSESESSIONIDCOOKIE=UUID666777888; Path=/; HttpOnly"); cookie.saveTo(request, response); log.trace("Set session ID cookie for session with id {}", idString); }
获得Session的Id
public Serializable getSessionId(SessionKey key) {
// 首先试图从SessionKey中获得Session的Id Serializable id = super.getSessionId(key); if (id == null && WebUtils.isWeb(key)) { ServletRequest request = WebUtils.getRequest(key); ServletResponse response = WebUtils.getResponse(key);
// 如果没有获得到再试图从Cookie中获得 id = getSessionId(request, response); } return id; }
Session过期
protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) { // 首先更新介质中的Session super.onExpiration(s, ese, key); // 然后删除SessionIdCookie onInvalidation(key); }