We know that shiro manages Session through SessionManager, and the operation of Session is implemented through SessionDao. By default, shiro implements two SessionDao, namely CachingSessionDAO and MemorySessionDAO. When we use EhCache cache, we use CachingSessionDAO. If the cache is not applicable, we will choose memory-based SessionDao. Therefore, if we want to implement distributed Session sharing based on Redis, the focus is on rewriting SessionDao in SessionManager. Our rewrite code is as follows:
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.steretype.Service; @Service @SuppressWarnings({ "rawtypes", "unchecked" }) public class RedisSessionDao extends AbstractSessionDAO { // Session timeout time, unit is milliseconds private long expireTime = 120000; @Autowired private RedisTemplate redisTemplate;// Redis operation class, if you are not familiar with this, you can refer to the previous blog public RedisSessionDao() { super(); } public RedisSessionDao(long expireTime, RedisTemplate redisTemplate) { super(); this.expireTime = expireTime; this.redisTemplate = redisTemplate; } @Override // Update session public void update(Session session) throws UnknownSessionException { System.out.println("================================================================================================================================================================================================================================================================================================================================================================================================================ session.getId() == null) { return; } session.setTimeout(expireTime); redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.MILLISECONDS); } @Override // Delete session public void delete(Session session) { System.out.println("====================================================================================================================================================================================================================================================================================================================================================================================================================== redisTemplate.opsForValue().getOperations().delete(session.getId()); } @Override// Get the active session, which can be used to count the number of people online. If you want to implement this function, you can specify a session prefix when adding the session to redis. When counting, use keys("session-prefix*") to blur the search for all session collections in redis public Collection<Session> getActiveSessions() { System.out.println("=================================================================================================================================================================================================================================================================================================================================================================================== redisTemplate.keys("*"); } @Override// Join session protected Serializable doCreate(Session session) { System.out.println("============================================================================================================================================================================================================================================================================================================================================================================================================================================================================= TimeUnit.MILLISECONDS); return sessionId; } @Override// Read session protected Session doReadSession(Serializable sessionId) { System.out.println("===================================================================================================================================================================================================================================================================================================================================================================================================================================================================== } public void setExpireTime(long expireTime) { this.expireTime = expireTime; } public RedisTemplate getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } } After SessionDao is implemented, we need to add SessionDao to SessionManager. The code is as follows:
@Bean public DefaultWebSessionManager configWebSessionManager(){ DefaultWebSessionManager manager = new DefaultWebSessionManager(); manager.setCacheManager(cacheManager);// Join the cache manager manager.setSessionDAO(sessionDao);// Set SessionDao manager.setDeleteInvalidSessions(true);// Delete expired session manager.setGlobalSessionTimeout(sessionDao.getExpireTime());// Set the global session timeout manager.setSessionValidationSchedulerEnabled(true);// Check session return manager at no time; } The last step is to configure SessionManager to SecurityManager
@Bean public SecurityManager securityManager(DefaultWebSessionManager webSessionManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // Set realm. securityManager.setRealm(myShiroRealm()); // Inject cache manager; securityManager.setCacheManager(cacheManager); // If this is executed multiple times, it is the same object; // Session Manager securityManager.setSessionManager(webSessionManager); //Inject Remember my manager; securityManager.setRememberMeManager(rememberMeManager()); return securityManager; } The test results are as follows:
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
=========================================
====================doReadSession=====================
====================doReadSession=====================
=========================================
====================doReadSession=====================
====================doReadSession=====================
====================doReadSession=====================
Permission Configuration -->MyShiroRealm.doGetAuthorizationInfo()
====================doReadSession=====================
We will find that when multiple resources exist in a page, doReadSession and update methods will be called constantly to read and update sessions. At present, no better solution has been found for this problem.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.