自從之前研究了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()方法,就能清空緩存上的信息了;