[toc]
由于项目中的shiro的缓存管理器替换为redis,故此处简略追踪记录过期session的销毁过程。
安全管理器SecurityManager可以说是shiro最最重要的组件
public Session start(SessionContext context) throws AuthorizationException {return this.sessionManager.start(context);}
public Session start(SessionContext context) {// 创建session:SimpleSessionSession session = createSession(context);//设置session的timeout时间:默认30分钟applyGlobalSessionTimeout(session);//根据sessionId 生成cookie存入到request response中onStart(session, context);//通知session监听器notifyStart(session);//Don't expose the EIS-tier Session object to the client-tier://把SimpleSession包装为DelegatingSessionreturn createExposedSession(session, context);}
protected Session createSession(SessionContext context) throws AuthorizationException {enableSessionValidationIfNecessary();return doCreateSession(context);}
在上文创建session的时候首选执行的是方法是enableSessionValidationIfNecessary,它开启了一个定时器
private void enableSessionValidationIfNecessary() {//获取session校验调度器SessionValidationScheduler scheduler = getSessionValidationScheduler();if (isSessionValidationSchedulerEnabled() && (scheduler == null || !scheduler.isEnabled())) {//启用session检验enableSessionValidation();}}
在追踪定时器源码之前,我们先看一下SimpleSession的基本属性有哪些
public class SimpleSession implements ValidatingSession, Serializable {//.....//session Idprivate transient Serializable id;//session的创建时间private transient Date startTimestamp;//session的停止时间private transient Date stopTimestamp;//session的最近一次访问时间,初始值是startTimestampprivate transient Date lastAccessTime;//session的有效时长,默认30分钟private transient long timeout;//session是否到期private transient boolean expired;//主机private transient String host;//存放的属性 session.setAttributes存入的属性private transient Map<Object, Object> attributes;//根据最后访问时间和有效时间判断 是否过期▲protected boolean isTimedOut() {//代码略}//更新最后访问时间 ▲public void touch() {this.lastAccessTime = new Date();}//session检验▲public void validate() throws InvalidSessionException {//check for stopped: stopTimestamp不为空 ▲if (isStopped()) {//timestamp is set, so the session is considered stopped:throw new StoppedSessionException(msg);}//check for expiration 过期了 ▲if (isTimedOut()) {//设置 expired = trueexpire();//throw an exception explaining details of why it expired:throw new ExpiredSessionException(msg);}}}
了解了SimpleSession的基本结构我,我们继续查看session检验定时器
上文的enableSessionValidation方法进入到的是ExecutorServiceSessionValidationScheduler的enableSessionValidation方法
public void enableSessionValidation() {// 创建ScheduledExecutorServicethis.service = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {//.....}});// 初始化service interval时长之后开始执行this的run方法,每隔interval执行一次;this.service.scheduleAtFixedRate(this, interval, interval, TimeUnit.MILLISECONDS);}this.enabled = true;}
public void run() {//....this.sessionManager.validateSessions();//....}
public void validateSessions() {//....//获取sessionDao中的全部sessionCollection<Session> activeSessions = getActiveSessions();//分别校验每个sessionfor (Session s : activeSessions) {SessionKey key = new DefaultSessionKey(s.getId());//真正的校验方法validate(s, key);}}
protected void validate(Session session, SessionKey key) throws InvalidSessionException {try {doValidate(session);} catch (ExpiredSessionException ese) {//从sessionDao中删除过期的sessiononExpiration(session, ese, key);throw ese;} catch (InvalidSessionException ise) {//从sessionDao中删除不合法的sessiononInvalidation(session, ise, key);throw ise;}}
if (session instanceof ValidatingSession) {((ValidatingSession) session).validate();} else {throw new IllegalStateException(msg);}
onExpiration方法从sessionDao中删除session▲▲▲
protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {onExpiration(s);notifyExpiration(s);afterExpired(s);}
afterExpired调用的是DefaultSessionManager的afterExpired方法
protected void afterExpired(Session session) {if (isDeleteInvalidSessions()) {delete(session);}}
了解shiro中最重要的对象securityManager是一个大管家,它管理着shiro生命周期的几乎所有的关联对象。
sessionManager的相关管理了session相关的所有操作,包括对session检验的定时器的定义,同时在session其他的操作的时候也会检验session的有效性