自从之前研究了security3一段时间,发现也不咋滴,后来转行去玩玩shiro,感觉还是挺不错的,小巧灵活;然后遇到个大家都应该遇到过的问题就是当用户退出或者异常关闭浏览器的时候不会自动清除缓存授权信息,当然shiro是有个玩意会自动扫描过期的会话,但是它只会清除会话信息不会清除cache里面的信息,看了网上的答案都是不靠谱的,最好还是自己看源码吧,下面看我的解决方案
<!-- 默认会话管理器 --> <bean id="sessionManager" class="com.shadow.shiro.extend.session.impl.SimpleWebSessionManager"> <property name="globalSessionTimeout" value="15000" /> <property name="sessionValidationInterval" value="30000" /> <property name="sessionValidationSchedulerEnabled" value="true" /> </bean>
全局的会话信息设置成15秒,检测扫描信息间隔30秒,第三个参数就是是否开启扫描
至于我的sessionManager实现类是自己继承,然后重写了其中一个方法
package com.shadow.shiro.extend.session.impl; import java.util.Collection; import java.util.Iterator; import org.apache.log4j.Logger; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.session.ExpiredSessionException; import org.apache.shiro.session.InvalidSessionException; import org.apache.shiro.session.Session; import org.apache.shiro.session.mgt.DefaultSessionKey; import org.apache.shiro.session.mgt.SessionKey; import org.apache.shiro.session.mgt.SimpleSession; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import com.shadow.shiro.extend.session.WebSessionManager; /** * 会话管理器 * * @author shadow * */ public class SimpleWebSessionManager extends DefaultWebSessionManager implements WebSessionManager { private CacheManager cacheManager; private final static Logger logger = Logger .getLogger(SimpleWebSessionManager.class); public SimpleWebSessionManager() { super(); } public void validateSessions() { if (logger.isInfoEnabled()) logger.info("Validating all active sessions..."); int invalidCount = 0; Collection<?> activeSessions = getActiveSessions(); if (activeSessions != null && !activeSessions.isEmpty()) { for (Iterator<?> i$ = activeSessions.iterator(); i$.hasNext();) { Session session = (Session) i$.next(); try { SessionKey key = new DefaultSessionKey(session.getId()); validate(session, key); } catch (InvalidSessionException e) { if (cacheManager != null) { SimpleSession s = (SimpleSession) session; if (s.getAttribute(SESSION_USER_KEY) != null) cacheManager.getCache(null).remove( s.getAttribute(SESSION_USER_KEY)); } if (logger.isDebugEnabled()) { boolean expired = e instanceof ExpiredSessionException; String msg = (new StringBuilder()).append( "Invalidated session with id [").append( session.getId()).append("]").append( expired ? " (expired)" : " (stopped)") .toString(); logger.debug(msg); } invalidCount++; } } } if (logger.isInfoEnabled()) { String msg = "Finished session validation."; if (invalidCount > 0) msg = (new StringBuilder()).append(msg).append(" [").append( invalidCount).append("] sessions were stopped.") .toString(); else msg = (new StringBuilder()).append(msg).append( " No sessions were stopped.").toString(); logger.info(msg); } } public void setCacheManager(CacheManager cacheManager) { this.cacheManager = cacheManager; } }
其中这里的方法是校验会话的,我在方法上加入了cachemanager的接口,然后重写set方法,就能获得实例,然后在执行期间调用cache.remove()方法,就能清空缓存上的信息了;