Shiro 4 sessionManager
来源:互联网 发布:时来天地皆同力 知乎 编辑:程序博客网 时间:2024/05/17 19:22
sessionManager接口
public interface SessionManager { Session start(SessionContext context); Session getSession(SessionKey key) throws SessionException;}
实现继承
AbstractSessionManager定义了session过期时间globalSessionTimeout
AbstractNativeSessionManager定义了Collection<SessionListener> listeners,我们可以实现SessionListener接口,在触发这些事件时候,做些事情
而这些listener起作用的地方就是
protected void notifyStart(Session session) { for (SessionListener listener : this.listeners) { listener.onStart(session); } } protected void notifyStop(Session session) { Session forNotification = beforeInvalidNotification(session); for (SessionListener listener : this.listeners) { listener.onStop(forNotification); } } protected void notifyExpiration(Session session) { Session forNotification = beforeInvalidNotification(session); for (SessionListener listener : this.listeners) { listener.onExpiration(forNotification); } }
这个类中有对start和getSession的实现
start方法
public Session start(SessionContext context) { Session session = createSession(context); applyGlobalSessionTimeout(session); onStart(session, context); notifyStart(session); //Don't expose the EIS-tier Session object to the client-tier: return createExposedSession(session, context); }protected abstract Session createSession(SessionContext context) throws AuthorizationException;protected void onStart(Session session, SessionContext context) { }protected Session createExposedSession(Session session, SessionContext context) { return new DelegatingSession(this, new DefaultSessionKey(session.getId())); }
getSession方法
public Session getSession(SessionKey key) throws SessionException { Session session = lookupSession(key); return session != null ? createExposedSession(session, key) : null; } private Session lookupSession(SessionKey key) throws SessionException { if (key == null) { throw new NullPointerException("SessionKey argument cannot be null."); } return doGetSession(key); } protected abstract Session doGetSession(SessionKey key) throws InvalidSessionException;
AbstractValidatingSessionManager作用是对所有的session检测,字段sessionValidationSchedulerEnabled默认为true,是否检测
sessionValidationScheduler是具体去执行检测的类
createSession方法的实现
protected Session createSession(SessionContext context) throws AuthorizationException { enableSessionValidationIfNecessary(); return doCreateSession(context); } protected abstract Session doCreateSession(SessionContext initData) throws AuthorizationException;
doGetSession方法实现
@Override protected final Session doGetSession(final SessionKey key) throws InvalidSessionException { enableSessionValidationIfNecessary(); log.trace("Attempting to retrieve session with key {}", key); Session s = retrieveSession(key); if (s != null) { validate(s, key); } return s; }/** * Looks up a session from the underlying data store based on the specified session key. * * @param key the session key to use to look up the target session. * @return the session identified by {@code sessionId}. * @throws UnknownSessionException if there is no session identified by {@code sessionId}. */ protected abstract Session retrieveSession(SessionKey key) throws UnknownSessionException;
其中都用到了enableSessionValidationIfNecessary();这个方法就是去检测
private void enableSessionValidationIfNecessary() { SessionValidationScheduler scheduler = getSessionValidationScheduler(); if (isSessionValidationSchedulerEnabled() && (scheduler == null || !scheduler.isEnabled())) { enableSessionValidation(); } }protected synchronized void enableSessionValidation() { SessionValidationScheduler scheduler = getSessionValidationScheduler(); if (scheduler == null) { scheduler = createSessionValidationScheduler(); setSessionValidationScheduler(scheduler); if (log.isInfoEnabled()) { log.info("Enabling session validation scheduler..."); } scheduler.enableSessionValidation(); afterSessionValidationEnabled(); } }protected SessionValidationScheduler createSessionValidationScheduler() { ExecutorServiceSessionValidationScheduler scheduler; if (log.isDebugEnabled()) { log.debug("No sessionValidationScheduler set. Attempting to create default instance."); } scheduler = new ExecutorServiceSessionValidationScheduler(this);//默认的 scheduler.setInterval(getSessionValidationInterval()); if (log.isTraceEnabled()) { log.trace("Created default SessionValidationScheduler instance of type [" + scheduler.getClass().getName() + "]."); } return scheduler; } protected void afterSessionValidationEnabled() { }
DefaultSessionManager是DefaultSecurityManager使用的默认实现,用于JavaSE环境,sessionFactory默认使用SimpleSessionFactory,
sessionDAO默认使用MemorySessionDAO
doCreateSession的实现
protected Session doCreateSession(SessionContext context) { Session s = newSessionInstance(context); if (log.isTraceEnabled()) { log.trace("Creating session for host {}", s.getHost()); } create(s); return s; } protected Session newSessionInstance(SessionContext context) { return getSessionFactory().createSession(context); } protected void create(Session session) { if (log.isDebugEnabled()) { log.debug("Creating new EIS record for new session instance [" + session + "]"); } sessionDAO.create(session); }
retrieveSession的实现
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException { Serializable sessionId = getSessionId(sessionKey); if (sessionId == null) { log.debug("Unable to resolve session ID from SessionKey [{}]. Returning null to indicate a " + "session could not be found.", sessionKey); return null; } Session s = retrieveSessionFromDataSource(sessionId); if (s == null) { //session ID was provided, meaning one is expected to be found, but we couldn't find one: String msg = "Could not find session with ID [" + sessionId + "]"; throw new UnknownSessionException(msg); } return s; }protected Serializable getSessionId(SessionKey sessionKey) { return sessionKey.getSessionId(); }protected Session retrieveSessionFromDataSource(Serializable sessionId) throws UnknownSessionException { return sessionDAO.readSession(sessionId); }
DefaultWebSessionManager用于Web环境的实现,可以替代ServletContainerSessionManager,自己维护着会话
public DefaultWebSessionManager() { Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME); cookie.setHttpOnly(true); //more secure, protects against XSS attacks this.sessionIdCookie = cookie; this.sessionIdCookieEnabled = true; }重写AbstractNativeSessionManager的onStart方法
/** * Stores the Session's ID, usually as a Cookie, to associate with future requests. * * @param session the session that was just {@link #createSession created}. */ @Override 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); if (isSessionIdCookieEnabled()) { Serializable sessionId = session.getId(); 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.saveTo(request, response); log.trace("Set session ID cookie for session with id {}", idString); }
getSessionId方法重写
@Override public Serializable getSessionId(SessionKey key) { Serializable id = super.getSessionId(key); if (id == null && WebUtils.isWeb(key)) { ServletRequest request = WebUtils.getRequest(key); ServletResponse response = WebUtils.getResponse(key); id = getSessionId(request, response); } return id; } protected Serializable getSessionId(ServletRequest request, ServletResponse response) { return getReferencedSessionId(request, response); } private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) { String id = getSessionIdCookieValue(request, response); //从cookie读取 if (id != null) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);//设置sessionid位置 } else { //not in a cookie, or cookie is disabled - try the request URI as a fallback (i.e. due to URL rewriting): //try the URI path segment parameters first: id = getUriPathSegmentParamValue(request, ShiroHttpSession.DEFAULT_SESSION_ID_NAME);//从url截取 if (id == null) { //not a URI path segment parameter, try the query parameters: String name = getSessionIdName(); id = request.getParameter(name);//从request的参数取 if (id == null) { //try lowercase: id = request.getParameter(name.toLowerCase()); } } if (id != null) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, ShiroHttpServletRequest.URL_SESSION_ID_SOURCE); } } if (id != null) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id); //automatically mark it valid here. If it is invalid, the //onUnknownSession method below will be invoked and we'll remove the attribute at that time. request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); } return id; }
重写了AbstractNativeSessionManager的createExposedSession,将DelegatingSession的key换成WebSessionKey
protected Session createExposedSession(Session session, SessionContext context) { if (!WebUtils.isWeb(context)) { return super.createExposedSession(session, context); } ServletRequest request = WebUtils.getRequest(context); ServletResponse response = WebUtils.getResponse(context); SessionKey key = new WebSessionKey(session.getId(), request, response); return new DelegatingSession(this, key); }
ServletContainerSessionManager implements WebSessionManager extends SessionManager
DefaultWebSecurityManager使用的默认实现,用于Web环境,其直接使用Servlet容器的会话
public class ServletContainerSessionManager implements WebSessionManager { //TODO - complete JavaDoc //TODO - read session timeout value from web.xml public ServletContainerSessionManager() { } public Session start(SessionContext context) throws AuthorizationException { return createSession(context); } 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); if (httpSession != null) { session = createSession(httpSession, request.getRemoteHost()); } return session; } private String getHost(SessionContext context) { String host = context.getHost(); if (host == null) { ServletRequest request = WebUtils.getRequest(context); if (request != null) { host = request.getRemoteHost(); } } return host; } /** * @since 1.0 */ protected Session createSession(SessionContext sessionContext) throws AuthorizationException { if (!WebUtils.isHttp(sessionContext)) { String msg = "SessionContext must be an HTTP compatible implementation."; throw new IllegalArgumentException(msg); } HttpServletRequest request = WebUtils.getHttpRequest(sessionContext); HttpSession httpSession = request.getSession(); //SHIRO-240: DO NOT use the 'globalSessionTimeout' value here on the acquired session. //see: https://issues.apache.org/jira/browse/SHIRO-240 String host = getHost(sessionContext); return createSession(httpSession, host); } protected Session createSession(HttpSession httpSession, String host) { return new HttpServletSession(httpSession, host); } /** * This implementation always delegates to the servlet container for sessions, so this method returns * {@code true} always. * * @return {@code true} always * @since 1.2 */public boolean isServletContainerSessions() {return true;}}
SessionManager使用在SessionsSecurityManager
private SessionManager sessionManager; /** * Default no-arg constructor, internally creates a suitable default {@link SessionManager SessionManager} delegate * instance. */ public SessionsSecurityManager() { super(); this.sessionManager = new DefaultSessionManager(); applyCacheManagerToSessionManager(); }
public Session start(SessionContext context) throws AuthorizationException { return this.sessionManager.start(context); } public Session getSession(SessionKey key) throws SessionException { return this.sessionManager.getSession(key); }
Subject中取得session最终是有securityManager完成
public Session getSession(boolean create) { if (log.isTraceEnabled()) { log.trace("attempting to get session; create = " + create + "; session is null = " + (this.session == null) + "; session has id = " + (this.session != null && session.getId() != null)); } if (this.session == null && create) { //added in 1.2: if (!isSessionCreationEnabled()) { String msg = "Session creation has been disabled for the current subject. This exception indicates " + "that there is either a programming error (using a session when it should never be " + "used) or that Shiro's configuration needs to be adjusted to allow Sessions to be created " + "for the current Subject. See the " + DisabledSessionException.class.getName() + " JavaDoc " + "for more."; throw new DisabledSessionException(msg); } log.trace("Starting session for host {}", getHost()); SessionContext sessionContext = createSessionContext(); Session session = this.securityManager.start(sessionContext); this.session = decorate(session); } return this.session; }
- Shiro 4 sessionManager
- Apache Shiro SessionManager
- shiro的会话管理器SessionManager
- SessionManager
- spring mvc+Mybatis整合shiro 第三章 SessionManager
- sessionManager定义
- tomcat源码解析--SessionManager
- Shiro 4
- 7.SessionManager(session生命周期管理)
- 【shiro】shiro 学习笔记4-初识shiro授权
- shiro笔记4《shiro默认拦截器》
- Apache shiro(4)-缓存
- shiro
- shiro
- Shiro
- shiro
- shiro
- shiro
- android 腾讯微博
- linux 端口转发工具
- 1
- redis配置jedisPool参数
- Java - Message Drive Bean - POC
- Shiro 4 sessionManager
- android 应用性能优化
- odoo 9.0创建自定义模块
- 图像像素中通道概念解析
- 编程之美 拒绝玄学 将帅问题简明解The problem of chinese chess about generals
- 发送短信之分割短信 SMSManager
- Android Material Design 之 有意义动效
- [iOS 文本输入限制]限制输入特定字符串等
- Android自定义View——使用贝塞尔曲线实现流量进度条