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了,然后进行封装。