shiro——session会话管理

目录

 

1. 会话

1.1 Session 接口

1.2 SessionManager 会话管理

1.3 SessionListener 会话监听

2. 会话持久化

2.1 SessionDAO接口

2.2 AbstractSessionDAO类

2.3 CachingSessionDAO 类

2.4 EnterpriseCacheSessionDAO 类

2.5 MemorySessionDAO 类

3. 会话过期验证

3.1 SessionValidationScheduler接口

3.2 ExecutorServiceSessionValidationScheduler 类 


1. 会话

当用户访问我们的应用时,为了方便,将用户的信息(不止是用户信息)保存起来,下次用户访问的时候,应用就能识别出用户。shiro也提供了会话机制,可以代替Web的会话机制,Session接口是会话的核心。

1.1 Session 接口、SimpleSession类

public interface Session {
    Serializable getId();
    Date getStartTimestamp();
    Date getLastAccessTime();
    long getTimeout() throws InvalidSessionException;
    void setTimeout(long var1) throws InvalidSessionException;
    String getHost();
    void touch() throws InvalidSessionException;
    void stop() throws InvalidSessionException;
    Collection<Object> getAttributeKeys() throws InvalidSessionException;
    Object getAttribute(Object var1) throws InvalidSessionException;
    void setAttribute(Object var1, Object var2) throws InvalidSessionException;
    Object removeAttribute(Object var1) throws InvalidSessionException;
}

可以看出会话可以保存的信息有:会话id,会话创建时间,最近一次访问会话的时间,会话超时时间,用户主机,键值对(用来存储一些额外自定义的数据的)。

Session接口的实现类有多个:SimpleSession(简单地实现了Session接口)

SimpleSession 简单的会话实现类,我们一般都用这个,当然还有其他的会话类。

public class SimpleSession implements ValidatingSession, Serializable {
    protected static final long MILLIS_PER_SECOND = 1000L; //这是一秒的常量
    protected static final long MILLIS_PER_MINUTE = 60000L; //一分钟的常量
    protected static final long MILLIS_PER_HOUR = 3600000L; //一小时的常量
    static int bitIndexCounter = 0;
    private static final int ID_BIT_MASK;
    private static final int START_TIMESTAMP_BIT_MASK;
    private static final int STOP_TIMESTAMP_BIT_MASK;
    private static final int LAST_ACCESS_TIME_BIT_MASK;
    private static final int TIMEOUT_BIT_MASK;
    private static final int EXPIRED_BIT_MASK;
    private static final int HOST_BIT_MASK;
    private static final int ATTRIBUTES_BIT_MASK;
    private transient Serializable id; //会话ID,就是Sessionid
    private transient Date startTimestamp; //会话开始时间
    private transient Date stopTimestamp; //会话结束时间
    private transient Date lastAccessTime; //上一次会话访问的时间
    private transient long timeout; //会话过期时间
    private transient boolean expired; //会话是否过期了
    private transient String host; //用户主机
    private transient Map<Object, Object> attributes; //会话的存储空间,可将用户的重要信息存进会话的attributes里面
    public SimpleSession() { 
        this.timeout = 1800000L;//默认会话过期时间为30分钟
        this.startTimestamp = new Date(); //会话开始时间就是创建会话的这一刻
        this.lastAccessTime = this.startTimestamp;//初始化时,上一次会话访问时间是创建时间
    }
    public SimpleSession(String host) { //可以设置用户主机的构造方法
        this();
        this.host = host;
    }
    //省略了get、set方法
    public void touch() { //访问了一次会话,更新“上一次访问时间”
        this.lastAccessTime = new Date();
    }
    public void stop() { //停止会话,设置结束时间
        if (this.stopTimestamp == null) {
            this.stopTimestamp = new Date();
        }
    }
    protected boolean isStopped() { //判断会话是否结束
        return this.getStopTimestamp() != null;
    }
    protected void expire() { //让会话过期
        this.stop();
        this.expired = true;
    }
    public boolean isValid() { //判断会话是否有效,即判断是否过期或者结束
        return !this.isStopped() && !this.isExpired();
    }
    protected boolean isTimedOut() { //判断会话是否超时
        if (this.isExpired()) {
            return true;
        } else {
            long timeout = this.getTimeout();
            if (timeout >= 0L) {
                Date lastAccessTime = this.getLastAccessTime();
                if (lastAccessTime == null) {
                    String msg = "session.lastAccessTime for session with id [" + this.getId() + "] is null.  This value must be set at least once, preferably at least upon instantiation.  Please check the " + this.getClass().getName() + " implementation and ensure this value will be set (perhaps in the constructor?)";
                    throw new IllegalStateException(msg);
                } else {
                    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 [" + this.getId() + "].  Session is not considered expired.");
                }

                return false;
            }
        }
    }
    public void validate() throws InvalidSessionException {//验证会话是否有效,无效则抛出异常
        if (this.isStopped()) {
            String msg = "Session with id [" + this.getId() + "] has been explicitly stopped.  No further interaction under this session is allowed.";
            throw new StoppedSessionException(msg);
        } else if (this.isTimedOut()) {
            this.expire();
            Date lastAccessTime = this.getLastAccessTime();
            long timeout = this.getTimeout();
            Serializable sessionId = this.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 / 1000L + " seconds (" + timeout / 60000L + " minutes)";
            if (log.isTraceEnabled()) {
                log.trace(msg);
            }
            throw new ExpiredSessionException(msg);
        }
    }
    private Map<Object, Object> getAttributesLazy() {//获取Attributes
        Map<Object, Object> attributes = this.getAttributes();
        if (attributes == null) {
            attributes = new HashMap();
            this.setAttributes((Map)attributes);
        }
        return (Map)attributes;
    }
    //获取Attributes的key集合
    public Collection<Object> getAttributeKeys() throws InvalidSessionException {
        Map<Object, Object> attributes = this.getAttributes();
        return attributes == null ? Collections.emptySet() : attributes.keySet();
    }
    public Object getAttribute(Object key) {//根据key找value
        Map<Object, Object> attributes = this.getAttributes();
        return attributes == null ? null : attributes.get(key);
    }
    public void setAttribute(Object key, Object value) { //添加A
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值