shiro学习09-用户以及登录-sessionManager

上面说了shiro对httpSession的封装,封装成shiro自己的session类,这里说如何建立shiro的session——SessionManager类。

SessionManager用于管理shiro的session的创建(不是httpSession),默认使用的是ServletContainerSessionManager,在defaultWebSecurityManager创建的时候就会实例化一个ServletContainerSessionManager实例。

源码如下:

public DefaultWebSecurityManager() {

        super();

        ((DefaultSubjectDAO) this.subjectDAO).setSessionStorageEvaluator(new DefaultWebSessionStorageEvaluator());

        this.sessionMode = HTTP_SESSION_MODE;

        setSubjectFactory(new DefaultWebSubjectFactory());

        setRememberMeManager(new CookieRememberMeManager());

        setSessionManager(new ServletContainerSessionManager());//创建sessionManager

}

 

关于创建session的源码

public Session getSession(SessionKey key) throws SessionException {

        if (!WebUtils.isHttp(key)) {

            String msg = "SessionKey must be an HTTP compatible implementation.";

            throw new IllegalArgumentException(msg);

        }

 

        HttpServletRequest request = WebUtils.getHttpRequest(key);

 

        Session session = null;

 

        HttpSession httpSession = request.getSession(false);//第一次访问时返回null

        if (httpSession != null) {//不会创建HttpServletSession

            session = createSession(httpSession, request.getRemoteHost());

        }

 

        return session;

    }

//createSession的方法:

protected Session createSession(HttpSession httpSession, String host) {

     return new HttpServletSession(httpSession, host);

}

从源码中可以看出:在浏览器发起第一次请求时shiro是不会涉及到任何session的,包括httpSession,他的调用HttpServletRequest.getSession(false),这个方法在第一次请求时返回的null。但是在以后(也就是不是第一次访问)时就会产生获得httpSession.

但是只有一种情况例外,就是第一次就是登陆的情况,在登陆候,同样会调用这个方法:org.apache.shiro.mgt.DefaultSubjectDAO.save(Subject)(只要访问就会调用,包括第一次访问时),但是如果第一次访问就是登录而且登录成功,那么这个subject的principalCollection就不是空,我们看一下save方法中调用的两个merger方法的部分源码:

Session session = subject.getSession(false);//仍然是false调用,第一次访问的话返回的仍然是空,

 

if (session == null) {

      if (!CollectionUtils.isEmpty(currentPrincipals)) {//但是如果已经登录成功则这个条件满足,

           session = subject.getSession();//这里就不再返回null,在delegatingSubject的源码中可以发现,

           session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, currentPrincipals);

      }

 

这里的subject是DelegatingSubject,我们再看一下他的getSession方法

public Session getSession() {

        return getSession(true);

}   然后在getSession(Boolean)方法中最终调用的是servetContainerSessionManager. createSession (sessionContext),里面调用的HttpServletRequest.getSession()这里我们就发现了这时候才会真正的取得session.

 

 

以上说的是第一次访问的时候session的获取以及封装,不是第一次的话通过第一次的getSeesion(False)就能获得session了,然后进行封装。

 

相关推荐