Shiro中的Session管理


Shiro中的Session管理

Shiro中Session有兩個來源:

  1. 獲取Servlet容器(如tomcat)的session。
  2. 使用自己的Session管理機制。

當我們在非web環境下(是的,Shiro可以在非web環境下身份驗證),肯定是第二種。

在web環境下的話,就看SessionManager的具體類型了。

我們常用的安全管理器是DefaultWebSecurityManager.繼承結構如下。

DefaultWebSecurityManager結構

在它的父類SessionsSecurityManager中包含sessionManager屬性。默認是DefaultSessionManager。

通過設置為DefaultWebSessionManager可以把session讓shiro來控制。

DefaultWebSessionManager結構

具體分析如下:

我們都知道shiro通過filter來攔截更改請求。

filter的繼承關系如下圖:

filter繼承關系

OncePerRequestFilter會調用doFilter方法,這個方法會調用doFilterInternal。

AbstractShiroFilter子類實現了doFilterInternal這個方法。這個方法繼續調用doFilterInternal ->prepareServletRequest -> wrapServletRequest。 wrapServletRequest這個方法,會根據域中securityManager的isHttpSessionMode方法來判斷是否采用servlet容器的session。(true:使用servlet容器的session,false:采用自定義session)。

public abstract class AbstractShiroFilter extends OncePerRequestFilter {
	protected ServletRequest wrapServletRequest(HttpServletRequest orig) {
        return new ShiroHttpServletRequest(orig, getServletContext(), isHttpSessions());
    }
    //......
}
public class ShiroHttpServletRequest extends HttpServletRequestWrapper {
public HttpSession getSession(boolean create) {

        HttpSession httpSession;

        if (isHttpSessions()) {
            httpSession = super.getSession(false);
            if (httpSession == null && create) {
                //Shiro 1.2: assert that creation is enabled (SHIRO-266):
                if (WebUtils._isSessionCreationEnabled(this)) {
                    httpSession = super.getSession(create);
                } else {
                    throw newNoSessionCreationException();
                }
            }
        } else {
            boolean existing = getSubject().getSession(false) != null;
            
            if (this.session == null || !existing) {
                Session shiroSession = getSubject().getSession(create);
                if (shiroSession != null) {
                    this.session = new ShiroHttpSession(shiroSession, this, this.servletContext);
                    if (!existing) {
                        setAttribute(REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
                    }
                } else if (this.session != null) {
                    this.session = null;
                }
            }
            httpSession = this.session;
        }

        return httpSession;
    }
    //......
}

可以看出,如果isHttpSessionMode結果為真,那么ShiroHttpServletRequest在getSession時會調用父類(HttpServletRequest)的結果,也就是servlet容器的結果。

但如果為假,則會new ShiroHttpSession來創建shiro自定義的session。

那么isHttpSessionMode的結果是怎么來的呢?

實現了這個方法的類是DefaultWebSessionManager,它的isHttpSessionMode方法中,會判斷它類中的字段sessionManager。如果sessionManager是WebSessionManager的子類,同時它的isServletContainerSessions方法返回真,那么整個方法就返回真。

public class DefaultWebSecurityManager extends DefaultSecurityManager implements WebSecurityManager {
    public boolean isHttpSessionMode() {
        SessionManager sessionManager = getSessionManager();
        return sessionManager instanceof WebSessionManager && ((WebSessionManager)sessionManager).isServletContainerSessions();
    }
    public SessionManager getSessionManager() {
        return this.sessionManager;
    }
    //.....
}

(還是挺繞的)

相關文章:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM