7.SessionManager(session生命周期管理)

来源:互联网 发布:网络贷款骗局 编辑:程序博客网 时间:2024/06/07 12:41

SessionManager负责管理shiro自己封装的session的生命周期。
为什么shiro要自己封装session?
1.可以为任意应用提供session支持,不依赖于底层容器
2.简单扩容session管理容器,可以实现任何数据源(redis,ehcache)来管理session,而不必担心jvm内存溢出

这里写图片描述
1.SessionManager

public interface SessionManager {    //根据指定的上下文SessionContext交由SessionFactory初始化个新的session    Session start(SessionContext context);    //根据指定的上下文信息(SessonId..)获取一个session,如果不存在返回null,如果存在但是失效,则抛出异常SessionException    Session getSession(SessionKey key) throws SessionException;}

2.AbstractSessionManager

/**AbstractSessionManager是SessionManager的顶层抽象类,主要提供Session存活时间管理的支持,默认session存活时间是30分钟deprecate this class (see SHIRO-240):这个类主要为子类提供一个常用的属性“globalSessionTimeout”的支持,最初设计是为ServletContainerSessionManager和AbstractNativeSessionManager提供session存活时间管理支持,但是ServletContainerSessionManager的实现并没有使用该“globalSessionTimeout”,这意味着只有AbstractNativeSessionManager需要使用。所以该类没有存在必要了。https://issues.apache.org/jira/browse/SHIRO-240**/public abstract class AbstractSessionManager implements SessionManager {    protected static final long MILLIS_PER_SECOND = 1000;    protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;    protected static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;    /**     * Default main session timeout value, equal to {@code 30} minutes.     */    public static final long DEFAULT_GLOBAL_SESSION_TIMEOUT = 30 * MILLIS_PER_MINUTE;    //默认为30分钟    private long globalSessionTimeout = DEFAULT_GLOBAL_SESSION_TIMEOUT;    public AbstractSessionManager() {    }    public long getGlobalSessionTimeout() {        return this.globalSessionTimeout;    }    //覆盖默认session存活时间30分钟    public void setGlobalSessionTimeout(long globalSessionTimeout) {        this.globalSessionTimeout = globalSessionTimeout;    }}

3.AbstractNativeSessionManager

/**该类基础父类AbstractSessionManager和实现NativeSessionManager接口(session操作方法规范),提供session的start、stop、Expiration状态的触发通知。**/public abstract class AbstractNativeSessionManager extends AbstractSessionManager implements NativeSessionManager {    private static final Logger log = LoggerFactory.getLogger(AbstractSessionManager.class);    //SESSION状态的触发通知(start、stop、Expiration)    private Collection<SessionListener> listeners;    public AbstractNativeSessionManager() {        this.listeners = new ArrayList<SessionListener>();    }    public void setSessionListeners(Collection<SessionListener> listeners) {        this.listeners = listeners != null ? listeners : new ArrayList<SessionListener>();    }    @SuppressWarnings({"UnusedDeclaration"})    public Collection<SessionListener> getSessionListeners() {        return this.listeners;    }    //实现SessionManager接口的start方法    public Session start(SessionContext context) {        //创建session        Session session = createSession(context);    //设置session过期时间        applyGlobalSessionTimeout(session);    //模板方法,子类对创建session后作出反应        onStart(session, context);    //创建session成功,迭代SessionListener执行onStart通知        notifyStart(session);        //返回一个包装过客户端层session,        return createExposedSession(session, context);    }    //根据上下文SessionContext创建Session,返回的session需要持久化状态,方便以后获取使用    protected abstract Session createSession(SessionContext context) throws AuthorizationException;    //设置session过期时间    protected void applyGlobalSessionTimeout(Session session) {        session.setTimeout(getGlobalSessionTimeout());    //session改变模板方法,子类对session改变作出反应。如:保存改变后的session        onChange(session);    }    //模板方法:子类对session start后作出反应    protected void onStart(Session session, SessionContext context) {    }    //根据sessionKey获取Session    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);    }    //获取session,如果session为null则抛异常UnknownSessionException    private Session lookupRequiredSession(SessionKey key) throws SessionException {        Session session = lookupSession(key);        if (session == null) {            String msg = "Unable to locate required Session instance based on SessionKey [" + key + "].";            throw new UnknownSessionException(msg);        }        return session;    }    //子类实现抽象方法根据sessonKey获取session    protected abstract Session doGetSession(SessionKey key) throws InvalidSessionException;    //封装返回客户端层session    protected Session createExposedSession(Session session, SessionContext context) {        return new DelegatingSession(this, new DefaultSessionKey(session.getId()));    }    //封装返回客户端层session    protected Session createExposedSession(Session session, SessionKey key) {        return new DelegatingSession(this, new DefaultSessionKey(session.getId()));    }    //当session过期或者停止时,需要调用通知。再调用通知前先包装下session为不可变session,防止SessionListener修改    protected Session beforeInvalidNotification(Session session) {        //ImmutableProxiedSession的实现即对session凡是有修改意向的方法进行重写为抛异常。        return new ImmutableProxiedSession(session);    }    //session start创建后调用SessionListener的onStart通知    protected void notifyStart(Session session) {        for (SessionListener listener : this.listeners) {            listener.onStart(session);        }    }    //session stop后调用SessionListener的onStop通知    protected void notifyStop(Session session) {        Session forNotification = beforeInvalidNotification(session);        for (SessionListener listener : this.listeners) {            listener.onStop(forNotification);        }    }    //session Expiration后调用SessionListener的onExpiration通知    protected void notifyExpiration(Session session) {        Session forNotification = beforeInvalidNotification(session);        for (SessionListener listener : this.listeners) {            listener.onExpiration(forNotification);        }    }    //根据sessionKey 获取session的创建时间    public Date getStartTimestamp(SessionKey key) {        return lookupRequiredSession(key).getStartTimestamp();    }    //根据sessionKey 获取session最后访问时间    public Date getLastAccessTime(SessionKey key) {        return lookupRequiredSession(key).getLastAccessTime();    }    //根据sessionKey 获取session过期时间.  负数:则永远不过期 正数:毫秒内有效    public long getTimeout(SessionKey key) throws InvalidSessionException {        return lookupRequiredSession(key).getTimeout();    }    //根据sessionKey设置session过期时间    public void setTimeout(SessionKey key, long maxIdleTimeInMillis) throws InvalidSessionException {        Session s = lookupRequiredSession(key);        s.setTimeout(maxIdleTimeInMillis);        onChange(s);    }    //根据sessionKey修改session最后访问时间    public void touch(SessionKey key) throws InvalidSessionException {        Session s = lookupRequiredSession(key);        s.touch();        onChange(s);    }    //根据sessionKey获取session 访问IP..    public String getHost(SessionKey key) {        return lookupRequiredSession(key).getHost();    }    //根据sessionKey 获取session里的设置的属性    public Collection<Object> getAttributeKeys(SessionKey key) {        Collection<Object> c = lookupRequiredSession(key).getAttributeKeys();        if (!CollectionUtils.isEmpty(c)) {        //如果不为空,则返回个不可修改的属性集合            return Collections.unmodifiableCollection(c);        }        return Collections.emptySet();    }    //根据sessionKey和属性key获取值    public Object getAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException {        return lookupRequiredSession(sessionKey).getAttribute(attributeKey);    }    //根据sessionKey、属性key、属性value设置属性值    public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException {        if (value == null) {            removeAttribute(sessionKey, attributeKey);        } else {            Session s = lookupRequiredSession(sessionKey);            s.setAttribute(attributeKey, value);        //session改变模板方法,子类对session改变作出反应。如:保存改变后的session            onChange(s);        }    }    //删除session属性值    public Object removeAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException {        Session s = lookupRequiredSession(sessionKey);        Object removed = s.removeAttribute(attributeKey);        if (removed != null) {            //session改变模板方法,子类对session改变作出反应。如:保存改变后的session            onChange(s);        }        return removed;    }    //判断session是否过期    public boolean isValid(SessionKey key) {        try {        //检查session是否过期            checkValid(key);            return true;        } catch (InvalidSessionException e) {            return false;        }    }    //停止该session    public void stop(SessionKey key) throws InvalidSessionException {        Session session = lookupRequiredSession(key);        try {            if (log.isDebugEnabled()) {                log.debug("Stopping session with id [" + session.getId() + "]");            }            session.stop();        //执行session 停止模板方法            onStop(session, key);        //执行session停止通知            notifyStop(session);        } finally {            afterStopped(session);        }    }    //session停止模板方法    protected void onStop(Session session, SessionKey key) {        onStop(session);    }    //修改session停止后的状态    protected void onStop(Session session) {        onChange(session);    }    //在session停止后执行该方法。如:删除session    protected void afterStopped(Session session) {    }    //检查session是否有效,即获取一个非null,非过期的session    public void checkValid(SessionKey key) throws InvalidSessionException {        //just try to acquire it.  If there is a problem, an exception will be thrown:        lookupRequiredSession(key);    }    //对session修改作出反应的模板方法    protected void onChange(Session s) {    }}

4.AbstractValidatingSessionManager

/**AbstractValidatingSessionManager继承于AbstractNativeSessionManager且实现了ValidatingSessionManager接口,该抽象类主要提供session验证和过期session检测。**/public abstract class AbstractValidatingSessionManager extends AbstractNativeSessionManager        implements ValidatingSessionManager, Destroyable {    private static final Logger log = LoggerFactory.getLogger(AbstractValidatingSessionManager.class);    //默认每小时检测一次    public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = MILLIS_PER_HOUR;    //是否开启session验证检测    protected boolean sessionValidationSchedulerEnabled;    //该接口主要代理SessionManager.validateSessions()方法,定时对session验证检测。如:过期的session则销毁等    protected SessionValidationScheduler sessionValidationScheduler;    //该属性是定义多长时间检测一次,这个值需要根据用户的实际情况来选择,定义的太小,则检测频繁对系统性能有影响.    protected long sessionValidationInterval;    public AbstractValidatingSessionManager() {        //默认开启检测        this.sessionValidationSchedulerEnabled = true;    //默认每小时检测一次        this.sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;    }    public boolean isSessionValidationSchedulerEnabled() {        return sessionValidationSchedulerEnabled;    }    @SuppressWarnings({"UnusedDeclaration"})    public void setSessionValidationSchedulerEnabled(boolean sessionValidationSchedulerEnabled) {        this.sessionValidationSchedulerEnabled = sessionValidationSchedulerEnabled;    }    public void setSessionValidationScheduler(SessionValidationScheduler sessionValidationScheduler) {        this.sessionValidationScheduler = sessionValidationScheduler;    }    public SessionValidationScheduler getSessionValidationScheduler() {        return sessionValidationScheduler;    }    //确保sessionValidation功能是开启的且有效的    private void enableSessionValidationIfNecessary() {        SessionValidationScheduler scheduler = getSessionValidationScheduler();    //如果该类允许sessionValidation功能开启且scheduler无效的,则执行enableSessionValidation创建SessionValidationScheduler        if (isSessionValidationSchedulerEnabled() && (scheduler == null || !scheduler.isEnabled())) {            enableSessionValidation();        }    }    public void setSessionValidationInterval(long sessionValidationInterval) {        this.sessionValidationInterval = sessionValidationInterval;    }    public long getSessionValidationInterval() {        return sessionValidationInterval;    }    @Override    protected final Session doGetSession(final SessionKey key) throws InvalidSessionException {        //这里我觉得会有并发问题,导致创建scheduler多次,且实现方式有问题,为什么要在使用session的地方确保每次都开启呢?        enableSessionValidationIfNecessary();        log.trace("Attempting to retrieve session with key {}", key);    //根据sessionKey获取session        Session s = retrieveSession(key);    //如果session不为null,则检测session是否有效的        if (s != null) {            validate(s, key);        }        return s;    }    //根据sessionKey获取session    protected abstract Session retrieveSession(SessionKey key) throws UnknownSessionException;    protected Session createSession(SessionContext context) throws AuthorizationException {        enableSessionValidationIfNecessary();        return doCreateSession(context);    }    //子类实现创建session    protected abstract Session doCreateSession(SessionContext initData) throws AuthorizationException;    //验证session    protected void validate(Session session, SessionKey key) throws InvalidSessionException {        try {            doValidate(session);        } catch (ExpiredSessionException ese) {        //session过期异常            onExpiration(session, ese, key);            throw ese;        } catch (InvalidSessionException ise) {        //session停止无效异常            onInvalidation(session, ise, key);            throw ise;        }    }    //处理过期session    protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {        log.trace("Session with id [{}] has expired.", s.getId());        try {            onExpiration(s);        //session过期通知            notifyExpiration(s);        } finally {        //最后处理过期session。如:删除session            afterExpired(s);        }    }    protected void onExpiration(Session session) {        onChange(session);    }    protected void afterExpired(Session session) {    }    //处理无效session    protected void onInvalidation(Session s, InvalidSessionException ise, SessionKey key) {        if (ise instanceof ExpiredSessionException) {            onExpiration(s, (ExpiredSessionException) ise, key);            return;        }        log.trace("Session with id [{}] is invalid.", s.getId());        try {        //对停止session作出处理:如:设置停止时间为最后访问时间            onStop(s);        //调用session停止通知            notifyStop(s);        } finally {        //session停止后作出处理,如:删除session            afterStopped(s);        }    }    //执行session的验证机制,实则交由session自己的validate();    protected void doValidate(Session session) throws InvalidSessionException {        if (session instanceof ValidatingSession) {            ((ValidatingSession) session).validate();        } else {            String msg = "The " + getClass().getName() + " implementation only supports validating " +                    "Session implementations of the " + ValidatingSession.class.getName() + " interface.  " +                    "Please either implement this interface in your session implementation or override the " +                    AbstractValidatingSessionManager.class.getName() + ".doValidate(Session) method to perform validation.";            throw new IllegalStateException(msg);        }    }    /**     * 这我也搞不懂干嘛的。。     * Subclass template hook in case per-session timeout is not based on     * {@link org.apache.shiro.session.Session#getTimeout()}.     * <p/>     * <p>This implementation merely returns {@link org.apache.shiro.session.Session#getTimeout()}</p>     *     * @param session the session for which to determine session timeout.     * @return the time in milliseconds the specified session may remain idle before expiring.     */    protected long getTimeout(Session session) {        return session.getTimeout();    }    //确保sessionValidation有效    protected void enableSessionValidation() {        SessionValidationScheduler scheduler = getSessionValidationScheduler();        if (scheduler == null) {        //如果为null。则创建个新的SessionValidationScheduler且设置到this.SessionValidationScheduler            scheduler = createSessionValidationScheduler();            setSessionValidationScheduler(scheduler);        }        if (log.isInfoEnabled()) {            log.info("Enabling session validation scheduler...");        }    //启动SessionValidationScheduler里的验证机制        scheduler.enableSessionValidation();    //开启session验证后可以作出你的逻辑处理。目前shiro没有实现任何功能,你可根据你需求来决定。    //如:记录每次开启时间        afterSessionValidationEnabled();    }    //创建SessionValidationScheduler    protected SessionValidationScheduler createSessionValidationScheduler() {        ExecutorServiceSessionValidationScheduler scheduler;        if (log.isDebugEnabled()) {            log.debug("No sessionValidationScheduler set.  Attempting to create default instance.");        }    //创建ExecutorServiceSessionValidationScheduler且设置本实例进去,因为scheduler需要代理本实例的validateSessions        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() {    }    //销毁SessionValidation    protected void disableSessionValidation() {        beforeSessionValidationDisabled();        SessionValidationScheduler scheduler = getSessionValidationScheduler();        if (scheduler != null) {            try {            //先执行SessionValidationScheduler自己的disableSessionValidation                scheduler.disableSessionValidation();                if (log.isInfoEnabled()) {                    log.info("Disabled session validation scheduler.");                }            } catch (Exception e) {                if (log.isDebugEnabled()) {                    String msg = "Unable to disable SessionValidationScheduler.  Ignoring (shutting down)...";                    log.debug(msg, e);                }            }            LifecycleUtils.destroy(scheduler);        //设置this.SessionValidationScheduler为null            setSessionValidationScheduler(null);        }    }    protected void beforeSessionValidationDisabled() {    }    public void destroy() {        disableSessionValidation();    }    //所有session真正的检测验证逻辑    public void validateSessions() {        if (log.isInfoEnabled()) {            log.info("Validating all active sessions...");        }        //用来记录当前这一批次检验到session过期或者无效的总数        int invalidCount = 0;        //获取sessionDAO中当前所有存在session,包括无效、过期的        Collection<Session> activeSessions = getActiveSessions();        /**        当你用户量如果非常大时候,假如有1亿个session,那么迭代会花很长时间且在这一阶段里会影响性能.可以分批次    **/        if (activeSessions != null && !activeSessions.isEmpty()) {            for (Session s : activeSessions) {                try {                    //simulate a lookup key to satisfy the method signature.                    //this could probably stand to be cleaned up in future versions:                    SessionKey key = new DefaultSessionKey(s.getId());            //验证session                    validate(s, key);                } catch (InvalidSessionException e) {                    if (log.isDebugEnabled()) {                        boolean expired = (e instanceof ExpiredSessionException);                        String msg = "Invalidated session with id [" + s.getId() + "]" +                                (expired ? " (expired)" : " (stopped)");                        log.debug(msg);                    }                    invalidCount++;                }            }        }        if (log.isInfoEnabled()) {            String msg = "Finished session validation.";            if (invalidCount > 0) {                msg += "  [" + invalidCount + "] sessions were stopped.";            } else {                msg += "  No sessions were stopped.";            }            log.info(msg);        }    }    //获取sessionDAO中当前所有存在session,包括无效、过期的    protected abstract Collection<Session> getActiveSessions();}

5.DefaultSessionManager

/**DefaultSessionManager继承AbstractValidatingSessionManager且实现CacheManagerAware接口,该具体实现类实现缓存接口CacheManagerAware只是为了让SessionDAO使用。所有关于session的状态的改变都是交由DefaultSessionManager的sessionDAO处理。**/public class DefaultSessionManager extends AbstractValidatingSessionManager implements CacheManagerAware {    private static final Logger log = LoggerFactory.getLogger(DefaultSessionManager.class);    //SessionFactory用来根据上下文创建新session    private SessionFactory sessionFactory;    //SessionDAO实现了缓存机制,所以用户只要实现第三方缓存,不依赖于JVM,就不必担心session过多导致内存溢出    protected SessionDAO sessionDAO;  //todo - move SessionDAO up to AbstractValidatingSessionManager?    //缓存管理器    private CacheManager cacheManager;    /**    是否删除session,如果session过期或者无效后。但是有些系统需要获取及时过期或者无效的SESSION。    默认为true。如果设置为false,需要用户自己有办法在外部去管理过期或者无效session    **/    private boolean deleteInvalidSessions;    public DefaultSessionManager() {        this.deleteInvalidSessions = true;        this.sessionFactory = new SimpleSessionFactory();        this.sessionDAO = new MemorySessionDAO();    }    public void setSessionDAO(SessionDAO sessionDAO) {        this.sessionDAO = sessionDAO;    //设置CacheManager到SessionDAO        applyCacheManagerToSessionDAO();    }    public SessionDAO getSessionDAO() {        return this.sessionDAO;    }    public SessionFactory getSessionFactory() {        return sessionFactory;    }    public void setSessionFactory(SessionFactory sessionFactory) {        this.sessionFactory = sessionFactory;    }    //session过期或者无效后是否删除    public boolean isDeleteInvalidSessions() {        return deleteInvalidSessions;    }    @SuppressWarnings({"UnusedDeclaration"})    public void setDeleteInvalidSessions(boolean deleteInvalidSessions) {        this.deleteInvalidSessions = deleteInvalidSessions;    }    //设置缓存管理器    public void setCacheManager(CacheManager cacheManager) {        this.cacheManager = cacheManager;    //设置缓存管理器到SessionDAO        applyCacheManagerToSessionDAO();    }    private void applyCacheManagerToSessionDAO() {        //如果缓存管理器和SessionDAO都不null,且SessionDAO实现了CacheManagerAware,则设置CacheManager到SessionDAO        if (this.cacheManager != null && this.sessionDAO != null && this.sessionDAO instanceof CacheManagerAware) {            ((CacheManagerAware) this.sessionDAO).setCacheManager(this.cacheManager);        }    }    //根据session上下文SessionContext创建Session    protected Session doCreateSession(SessionContext context) {        //调用SessionFactory创建session        Session s = newSessionInstance(context);        if (log.isTraceEnabled()) {            log.trace("Creating session for host {}", s.getHost());        }    //保存session到SessionDAO        create(s);        return s;    }    //调用SessionFactory创建session    protected Session newSessionInstance(SessionContext context) {        return getSessionFactory().createSession(context);    }    //保存session到SessionDAO    protected void create(Session session) {        if (log.isDebugEnabled()) {            log.debug("Creating new EIS record for new session instance [" + session + "]");        }        sessionDAO.create(session);    }    @Override    protected void onStop(Session session) {        if (session instanceof SimpleSession) {            SimpleSession ss = (SimpleSession) session;            Date stopTs = ss.getStopTimestamp();            ss.setLastAccessTime(stopTs);        }        onChange(session);    }    @Override    protected void afterStopped(Session session) {        if (isDeleteInvalidSessions()) {            delete(session);        }    }    protected void onExpiration(Session session) {        if (session instanceof SimpleSession) {            ((SimpleSession) session).setExpired(true);        }        onChange(session);    }    @Override    protected void afterExpired(Session session) {        if (isDeleteInvalidSessions()) {            delete(session);        }    }    protected void onChange(Session session) {        sessionDAO.update(session);    }    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;        }    //根据sessionID从SessionDAO中获取相对应的Session        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;    }    //获取sessionKey里的SessionID    protected Serializable getSessionId(SessionKey sessionKey) {        return sessionKey.getSessionId();    }    //根据sessionID从SessionDAO中获取相对应的Session    protected Session retrieveSessionFromDataSource(Serializable sessionId) throws UnknownSessionException {        return sessionDAO.readSession(sessionId);    }    //删除session    protected void delete(Session session) {        sessionDAO.delete(session);    }    //获取SessionDAO的存在session    protected Collection<Session> getActiveSessions() {        Collection<Session> active = sessionDAO.getActiveSessions();        return active != null ? active : Collections.<Session>emptySet();    }}

6.DefaultWebSessionManager

//基于WEB的SessionManager的实现  public class DefaultWebSessionManager extends DefaultSessionManager implements WebSessionManager {    private static final Logger log = LoggerFactory.getLogger(DefaultWebSessionManager.class);    //Cookie基本模板    private Cookie sessionIdCookie;    //是否存储sessionID到cookie中,默认没有设置存活时间,即保存在浏览器开辟的内存中,没有持久化在硬盘上    private boolean sessionIdCookieEnabled;    public DefaultWebSessionManager() {        Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);    //HttpOnly是防止用户通过js脚本获取cookie        cookie.setHttpOnly(true); //more secure, protects against XSS attacks        this.sessionIdCookie = cookie;    //默认允许存储sessionID到cookie中        this.sessionIdCookieEnabled = true;    }    //获取模板cookie    public Cookie getSessionIdCookie() {        return sessionIdCookie;    }    @SuppressWarnings({"UnusedDeclaration"})    public void setSessionIdCookie(Cookie sessionIdCookie) {        this.sessionIdCookie = sessionIdCookie;    }    public boolean isSessionIdCookieEnabled() {        return sessionIdCookieEnabled;    }    @SuppressWarnings({"UnusedDeclaration"})    public void setSessionIdCookieEnabled(boolean sessionIdCookieEnabled) {        this.sessionIdCookieEnabled = sessionIdCookieEnabled;    }    //存储sessionID到cookie中    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);    }    //删除浏览器SessionID cookie    private void removeSessionIdCookie(HttpServletRequest request, HttpServletResponse response) {        getSessionIdCookie().removeFrom(request, response);    }    //根据sessionID Cookie获取sessionid    private String getSessionIdCookieValue(ServletRequest request, ServletResponse response) {        if (!isSessionIdCookieEnabled()) {            log.debug("Session ID cookie is disabled - session id will not be acquired from a request cookie.");            return null;        }        if (!(request instanceof HttpServletRequest)) {            log.debug("Current request is not an HttpServletRequest - cannot get session ID cookie.  Returning null.");            return null;        }        HttpServletRequest httpRequest = (HttpServletRequest) request;    //从Cookie中读取sessionID        return getSessionIdCookie().readValue(httpRequest, WebUtils.toHttp(response));    }    //该方法尝试通过多种办法获取SessionID    private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {        //首先在cookie中获取sessionID        String id = getSessionIdCookieValue(request, response);        if (id != null) {        //设置获取SessionID的来源 Cookie            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,                    ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);        } else {            //cookie不存在,尝试通过uri中获取            id = getUriPathSegmentParamValue(request, ShiroHttpSession.DEFAULT_SESSION_ID_NAME);            if (id == null) {                //尝试中request的参数中获取                String name = getSessionIdName();                id = request.getParameter(name);                if (id == null) {                    id = request.getParameter(name.toLowerCase());                }            }            if (id != null) {        //设置获取SessionID的来源 URL                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,                        ShiroHttpServletRequest.URL_SESSION_ID_SOURCE);            }        }        if (id != null) {        //设置SessionUD             request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);            //设置SessionID有效.            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);        }        return id;    }    //通过URI获取SessionID    private String getUriPathSegmentParamValue(ServletRequest servletRequest, String paramName) {        if (!(servletRequest instanceof HttpServletRequest)) {            return null;        }        HttpServletRequest request = (HttpServletRequest)servletRequest;        String uri = request.getRequestURI();        if (uri == null) {            return null;        }        int queryStartIndex = uri.indexOf('?');        if (queryStartIndex >= 0) { //get rid of the query string            uri = uri.substring(0, queryStartIndex);        }        int index = uri.indexOf(';'); //now check for path segment parameters:        if (index < 0) {            //no path segment params - return:            return null;        }        //there are path segment params, let's get the last one that may exist:        final String TOKEN = paramName + "=";        uri = uri.substring(index+1); //uri now contains only the path segment params        //we only care about the last JSESSIONID param:        index = uri.lastIndexOf(TOKEN);        if (index < 0) {            //no segment param:            return null;        }        uri = uri.substring(index + TOKEN.length());        index = uri.indexOf(';'); //strip off any remaining segment params:        if(index >= 0) {            uri = uri.substring(0, index);        }        return uri; //what remains is the value    }    //获取sessionid存储的名字    private String getSessionIdName() {        String name = this.sessionIdCookie != null ? this.sessionIdCookie.getName() : null;        if (name == null) {            name = ShiroHttpSession.DEFAULT_SESSION_ID_NAME;        }        return name;    }    //封装一个基于WEB(包含request和response的支持)的 客户端层session,该方法主要用在新创建session    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);    }    //封装一个基于WEB(包含request和response的支持)的 客户端层session,该方法主要用在获取已存在的session    protected Session createExposedSession(Session session, SessionKey key) {        if (!WebUtils.isWeb(key)) {            return super.createExposedSession(session, key);        }        ServletRequest request = WebUtils.getRequest(key);        ServletResponse response = WebUtils.getResponse(key);        SessionKey sessionKey = new WebSessionKey(session.getId(), request, response);        return new DelegatingSession(this, sessionKey);    }    //session start创建后保存sessionID到客户端浏览器cookie中    @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);    //判断是否允许存储sessionID到cookie中        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);    //设置session为新创建        request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);    }    //获取sessionID    @Override    public Serializable getSessionId(SessionKey key) {        Serializable id = super.getSessionId(key);        if (id == null && WebUtils.isWeb(key)) {        //WebSessionKey中封装着request和response            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);    }    @Override    protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {        super.onExpiration(s, ese, key);        onInvalidation(key);    }    @Override    protected void onInvalidation(Session session, InvalidSessionException ise, SessionKey key) {        super.onInvalidation(session, ise, key);        onInvalidation(key);    }    //无效session后续操作    private void onInvalidation(SessionKey key) {        ServletRequest request = WebUtils.getRequest(key);        if (request != null) {            request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID);        }        if (WebUtils.isHttp(key)) {            log.debug("Referenced session was invalid.  Removing session ID cookie.");            removeSessionIdCookie(WebUtils.getHttpRequest(key), WebUtils.getHttpResponse(key));        } else {            log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response " +                    "pair. Session ID cookie will not be removed due to invalidated session.");        }    }    @Override    protected void onStop(Session session, SessionKey key) {        super.onStop(session, key);        if (WebUtils.isHttp(key)) {            HttpServletRequest request = WebUtils.getHttpRequest(key);            HttpServletResponse response = WebUtils.getHttpResponse(key);            //删除sessionID cookie            removeSessionIdCookie(request, response);        } else {            log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response " +                    "pair. Session ID cookie will not be removed due to stopped session.");        }    }    //用于判断是否使用serlvet的session    public boolean isServletContainerSessions() {        return false;    }}
0 0