shiro安全框架擴展教程--如何擴展實現集中式session管理

        上一章節我和大家分享的是如何擴展異步請求分支處理,這一章節我準備分享如何實現集中式session管理,shiro一大特色就是有自己一套session機制,與原生的httpsession差不多風格的api,用起來比較順手,我個人也比較喜歡;spring security是比較依賴與原生httpsession,所以比較難擴展這會話機制,但是我們shiro使用者就不用擔心這個問題,請大家準備好雞蛋殼,香蕉皮吧...


進入主題,我們先看看session管理器


<!-- 會話管理器 -->
	<bean id="sessionManager"
		class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
		<property name="sessionValidationSchedulerEnabled" value="false" />
		<property name="sessionDAO" ref="sessionDAO" />
		<property name="globalSessionTimeout" value="60000"/>
	</bean>

基本用到就三個參數sessionValidationSchedulerEnabled(掃描session線程,負責清理超時會話), sessionDao是進行會話讀寫的實現,globalSessionTimeout是會話存活時間(默認是30分鐘)


其他參數可看源碼配置,象session的cookie編號鍵之類的,有需要纔去改


下面看看我們的讀寫會話實現類


public class MCSessionDAO extends AbstractSessionDAO {

	private final static Logger log = LoggerFactory.getLogger(MCSessionDAO.class);

	private MemcachedClient client;

	public MCSessionDAO(MemcachedClient client) {
		if (client == null) {
			throw new RuntimeException("必須存在memcached客戶端實例");
		}
		this.client = client;
	}

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = generateSessionId(session);
		assignSessionId(session, sessionId);
		try {
			client.set(sessionId.toString(), (int) session.getTimeout() / 1000, session);
		} catch (Exception e) {
			log.error(e.getMessage());
		}
		return sessionId;
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		Session session = null;
		try {
			session = client.get(sessionId.toString());
		} catch (Exception e) {
			log.error(e.getMessage());
		}
		return session;
	}

	@Override
	public void delete(Session session) {
		try {
			client.delete(session.getId().toString());
		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}

	@Override
	public Collection<Session> getActiveSessions() {
		return Collections.emptySet();
	}

	@Override
	public void update(Session session) throws UnknownSessionException {
		try {
			client.replace(session.getId().toString(), (int) session.getTimeout() / 1000, session);
		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}

}


getActiveSessions這個方法是用來統計當前活動的session,但是memcached也沒有特別好的方法能獲取同一批鍵值對,暫時只能不支持方法,如果有朋友想到好的解決方案,望請告知下小弟



其實這個類跟普通的crud差不多,主要是通過設置memcached的過期時間來作爲session的存活時間,如果返回爲null則認爲session是登錄超時了,值得注意一個問題memcached應該需要評估足夠多的初始化內存,不然可能用戶量一上去,就可能有會話丟失的可能,畢竟內存不夠了memcached會自動把舊的一些數據擠出去,這要看memcached的失效策略設置


很明顯我們這裏的sessionDao實現類已經完成,然後配置到文件裏面


<!-- 會話讀寫實現類 -->
	<bean id="sessionDAO" class="com.silvery.security.shiro.session.MCSessionDAO">
		<constructor-arg ref="memcachedClient" />
	</bean>

如何配置memcached的客戶端實例我就不囉嗦,百度一大堆,把這個sessionDAO的編號注入到我們的sessionManager管理器裏面


然後我們的會話管理器又要配置到哪裏呢


<!-- 安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="sessionManager" ref="sessionManager" />
		<property name="cacheManager" ref="shiroCacheManager" />
		<property name="realm" ref="simpleUserRealm" />
	</bean>


然後就完工了,最後就配置個nginx+2個tomcat集羣下訪問測試下即可


歡迎拍磚...


發佈了57 篇原創文章 · 獲贊 211 · 訪問量 67萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章