您好,登錄后才能下訂單哦!
我們知道,shiro是通過SessionManager來管理Session的,而對于Session的操作則是通過SessionDao來實現的,默認的情況下,shiro實現了兩種SessionDao,分別為CachingSessionDAO和MemorySessionDAO,當我們使用EhCache緩存時,則是使用的CachingSessionDAO,不適用緩存的情況下,就會選擇基于內存的SessionDao.所以,如果我們想實現基于Redis的分布式Session共享,重點在于重寫SessionManager中的SessionDao。我們的重寫代碼如下:
package com.chhliu.springboot.shiro.cache; import java.io.Serializable; import java.util.Collection; import java.util.concurrent.TimeUnit; import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.apache.shiro.session.mgt.eis.AbstractSessionDAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @Service @SuppressWarnings({ "rawtypes", "unchecked" }) public class RedisSessionDao extends AbstractSessionDAO { // Session超時時間,單位為毫秒 private long expireTime = 120000; @Autowired private RedisTemplate redisTemplate;// Redis操作類,對這個使用不熟悉的,可以參考前面的博客 public RedisSessionDao() { super(); } public RedisSessionDao(long expireTime, RedisTemplate redisTemplate) { super(); this.expireTime = expireTime; this.redisTemplate = redisTemplate; } @Override // 更新session public void update(Session session) throws UnknownSessionException { System.out.println("===============update================"); if (session == null || session.getId() == null) { return; } session.setTimeout(expireTime); redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.MILLISECONDS); } @Override // 刪除session public void delete(Session session) { System.out.println("===============delete================"); if (null == session) { return; } redisTemplate.opsForValue().getOperations().delete(session.getId()); } @Override// 獲取活躍的session,可以用來統計在線人數,如果要實現這個功能,可以在將session加入redis時指定一個session前綴,統計的時候則使用keys("session-prefix*")的方式來模糊查找redis中所有的session集合 public Collection<Session> getActiveSessions() { System.out.println("==============getActiveSessions================="); return redisTemplate.keys("*"); } @Override// 加入session protected Serializable doCreate(Session session) { System.out.println("===============doCreate================"); Serializable sessionId = this.generateSessionId(session); this.assignSessionId(session, sessionId); redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.MILLISECONDS); return sessionId; } @Override// 讀取session protected Session doReadSession(Serializable sessionId) { System.out.println("==============doReadSession================="); if (sessionId == null) { return null; } return (Session) redisTemplate.opsForValue().get(sessionId); } public long getExpireTime() { return expireTime; } public void setExpireTime(long expireTime) { this.expireTime = expireTime; } public RedisTemplate getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } }
SessionDao實現完了之后,我們就需要將SessionDao加入SessionManager中了,代碼如下:
@Bean public DefaultWebSessionManager configWebSessionManager(){ DefaultWebSessionManager manager = new DefaultWebSessionManager(); manager.setCacheManager(cacheManager);// 加入緩存管理器 manager.setSessionDAO(sessionDao);// 設置SessionDao manager.setDeleteInvalidSessions(true);// 刪除過期的session manager.setGlobalSessionTimeout(sessionDao.getExpireTime());// 設置全局session超時時間 manager.setSessionValidationSchedulerEnabled(true);// 是否定時檢查session return manager; }
最后一步就是將SessionManager配置到SecurityManager中了
@Bean public SecurityManager securityManager(DefaultWebSessionManager webSessionManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 設置realm. securityManager.setRealm(myShiroRealm()); // 注入緩存管理器; securityManager.setCacheManager(cacheManager);// 這個如果執行多次,也是同樣的一個對象; // session管理器 securityManager.setSessionManager(webSessionManager); //注入記住我管理器; securityManager.setRememberMeManager(rememberMeManager()); return securityManager; }
測試結果如下:
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
===============update================
==============doReadSession=================
==============doReadSession=================
===============update================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
權限配置-->MyShiroRealm.doGetAuthorizationInfo()
==============doReadSession=================
我們會發現,當一個頁面中存在多個資源的時候,會不停的調用doReadSession,update方法來讀取和更新session,目前這個問題還沒有想到比較好的解決方案。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。