shiro安全框架擴充套件教程–異常退出沒有清除快取資訊處理方案

aielves發表於2013-12-11

自從之前研究了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()方法,就能清空快取上的資訊了;


相關文章