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);
}

参考:使用HttpOnly提升Cookie安全性

获得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);
}
原文地址:https://www.cnblogs.com/BINGJJFLY/p/9301352.html