• Shiro 关于校验Session过期、有效性的设计概念


    核心行为

    开启Session校验调度任务、校验所有的session、具体的Session自我校验、关闭Session校验调度任务

    核心类

    ValidatingSessionManager、SessionValidationScheduler、ValidatingSession

    ValidatingSessionManager的行为

    public interface ValidatingSessionManager extends SessionManager {
        // 校验所有的Session
        void validateSessions();
    }

    SessionValidationScheduler的行为

    public interface SessionValidationScheduler {
    
        // Session校验是否处于开启状态
        boolean isEnabled();
    
        // 开启Session校验 
        void enableSessionValidation();
    
        // 关闭Session校验
        void disableSessionValidation();
    
    }

    ValidatingSession的行为

    public interface ValidatingSession extends Session {
    
        // 校验是否处于开启状态
        boolean isValid();
    
        // Session自我校验
        void validate() throws InvalidSessionException;
    }

    校验过程解析

    ValidatingSessionManager开启Session校验调度任务 ==》 Session校验调度任务中使用ValidatingSessionManager校验所有的Session

    ==》 ValidatingSessionManager让其子类获得所有的Session(基础Session) ==》 各个基础Session自我校验

    ValidatingSessionManager开启Session校验调度任务

    protected SessionValidationScheduler sessionValidationScheduler;
    
    public void setSessionValidationScheduler(SessionValidationScheduler sessionValidationScheduler) {
        this.sessionValidationScheduler = sessionValidationScheduler;
    }
    
    protected synchronized void enableSessionValidation() {
        SessionValidationScheduler scheduler = getSessionValidationScheduler();
        if (scheduler == null) {
            scheduler = createSessionValidationScheduler();
            setSessionValidationScheduler(scheduler);
        }
        if (!scheduler.isEnabled()) {
            if (log.isInfoEnabled()) {
                log.info("Enabling session validation scheduler...");
            }
            // 开启Session校验调度任务
            scheduler.enableSessionValidation();
            afterSessionValidationEnabled();
        }
    }

    Session校验调度任务中使用ValidatingSessionManager校验所有的Session

    public void run() {
        if (log.isDebugEnabled()) {
            log.debug("Executing session validation...");
        }
        long startTime = System.currentTimeMillis();
        // Session校验任务调度时使用ValidatingSessionManager校验所有的Session
        this.sessionManager.validateSessions();
        long stopTime = System.currentTimeMillis();
        if (log.isDebugEnabled()) {
            log.debug("Session validation completed successfully in " + (stopTime - startTime) + " milliseconds.");
        }
    }

    ValidatingSessionManager让其子类获得所有的Session(基础Session)

    protected abstract Collection<Session> getActiveSessions();

    DefaultSessionManager具体执行获得所有的基础Session

    protected Collection<Session> getActiveSessions() {
        Collection<Session> active = sessionDAO.getActiveSessions();
        return active != null ? active : Collections.<Session>emptySet();
    }

    各个基础Session自我校验

    Collection<Session> activeSessions = getActiveSessions();
    if (activeSessions != null && !activeSessions.isEmpty()) {
        for (Session s : activeSessions) {
            try {
                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++;
            }
        }
    }
    
    protected void validate(Session session, SessionKey key) throws InvalidSessionException {
        try {
            doValidate(session);
        } catch (ExpiredSessionException ese) {
            onExpiration(session, ese, key);
            throw ese;
        } catch (InvalidSessionException ise) {
            onInvalidation(session, ise, key);
            throw ise;
        }
    }
    
    protected void doValidate(Session session) throws InvalidSessionException {
        if (session instanceof ValidatingSession) {
            // 基础Session根据自己拥有的属性值自我校验
            ((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);
        }
    }

    SimpleSession的自我校验

    public void validate() throws InvalidSessionException {
        // 校验Session是否已经被停止使用了,如果Session已经被停止使用了则抛出异常
        if (isStopped()) {
            String msg = "Session with id [" + getId() + "] has been " +
                    "explicitly stopped.  No further interaction under this session is " +
                    "allowed.";
            throw new StoppedSessionException(msg);
        }
    
        // 校验Session是否到了过期时间,如果Session已经到期了则抛出异常
        if (isTimedOut()) {
            expire();
            Date lastAccessTime = getLastAccessTime();
            long timeout = getTimeout();
    
            Serializable sessionId = getId();
    
            DateFormat df = DateFormat.getInstance();
            String msg = "Session with id [" + sessionId + "] has expired. " +
                    "Last access time: " + df.format(lastAccessTime) +
                    ".  Current time: " + df.format(new Date()) +
                    ".  Session timeout is set to " + timeout / MILLIS_PER_SECOND + " seconds (" +
                    timeout / MILLIS_PER_MINUTE + " minutes)";
            if (log.isTraceEnabled()) {
                log.trace(msg);
            }
            throw new ExpiredSessionException(msg);
        }
    }
    
    protected boolean isStopped() {
        return getStopTimestamp() != null;
    }
    
    protected boolean isTimedOut() {
        if (isExpired()) {
            return true;
        }
        long timeout = getTimeout();
        if (timeout >= 0l) {
            Date lastAccessTime = getLastAccessTime();
            if (lastAccessTime == null) {
                String msg = "session.lastAccessTime for session with id [" +
                        getId() + "] is null.  This value must be set at " +
                        "least once, preferably at least upon instantiation.  Please check the " +
                        getClass().getName() + " implementation and ensure " +
                        "this value will be set (perhaps in the constructor?)";
                throw new IllegalStateException(msg);
            }
            long expireTimeMillis = System.currentTimeMillis() - timeout;
            Date expireTime = new Date(expireTimeMillis);
            return lastAccessTime.before(expireTime);
        } else {
            if (log.isTraceEnabled()) {
                log.trace("No timeout for session with id [" + getId() +
                        "].  Session is not considered expired.");
            }
        }
        return false;
    }
    
    public boolean isExpired() {
        return expired;
    }
    
    protected void expire() {
        stop();
        this.expired = true;
    }
    
    public void stop() {
        if (this.stopTimestamp == null) {
            this.stopTimestamp = new Date();
        }
    }

    SimpleSession过期后自己无能为力,只能抛出异常交给AbstractValidatingSessionManager抓住异常进行特殊处理

    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);
        }
    }
    
    // 更新介质中的Session
    protected void onExpiration(Session session) { onChange(session); } protected void afterExpired(Session session) { }

    ValidatingSessionManager关闭Session校验调度任务

    protected synchronized void disableSessionValidation() {
        beforeSessionValidationDisabled();
        SessionValidationScheduler scheduler = getSessionValidationScheduler();
        if (scheduler != null) {
            try {
                // Session校验任务调度器禁用校验
                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);
            // 设置Session校验任务调度器为 null
            setSessionValidationScheduler(null);
        }
    }

    Session任务调度器禁用Session校验

    public void disableSessionValidation() {
        if (this.service != null) {
            this.service.shutdownNow();
        }
        this.enabled = false;
    }
  • 相关阅读:
    Spring:@ConfigurationProperties配置绑定
    Linux:性能诊断
    【第二章】:深浅拷贝剖析
    【第二章】:模块和运算符
    python 扩展注册功能装饰器举例
    python 函数 之 用户注册register()
    python 之 函数 基础
    python 函数
    python 文件操作
    python 的 数据类型
  • 原文地址:https://www.cnblogs.com/BINGJJFLY/p/9296144.html
Copyright © 2020-2023  润新知