spring integration redis implementation of shiro distributed session sharing methods
- 2021-01-06 00:38:43
- OfStack
By default, shiro implements two types of SessionDao, CachingSessionDAO and MemorySessionDAO. When we use EhCache caching, we use CachingSessionDAO. When caching is not available, we choose the memory-based SessionDao. So, if we want to implement distributed Session sharing based on Redis, the focus is to rewrite 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.stereotype.Service;
@Service
@SuppressWarnings({ "rawtypes", "unchecked" })
public class RedisSessionDao extends AbstractSessionDAO {
// Session Timeout time, in milliseconds
private long expireTime = 120000;
@Autowired
private RedisTemplate redisTemplate;// Redis Action classes, for those unfamiliar with this use, 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("===============update================");
if (session == null || 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("===============delete================");
if (null == session) {
return;
}
redisTemplate.opsForValue().getOperations().delete(session.getId());
}
@Override// Acquire active session , can be used to count the number of people online, if you want to achieve this function, can be in the session join redis Specified when the 1 a session Prefixes are used for statistics keys("session-prefix*") The way to fuzzy lookup redis All of the session A collection of
public Collection<Session> getActiveSessions() {
System.out.println("==============getActiveSessions=================");
return redisTemplate.keys("*");
}
@Override// join 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// read 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;
}
}
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);// Add the cache manager
manager.setSessionDAO(sessionDao);// Set up the SessionDao
manager.setDeleteInvalidSessions(true);// Delete expired session
manager.setGlobalSessionTimeout(sessionDao.getExpireTime());// Set the global session timeout
manager.setSessionValidationSchedulerEnabled(true);// Whether to check regularly session
return manager;
}
The last step is to configure SessionManager to SecurityManager
@Bean
public SecurityManager securityManager(DefaultWebSessionManager webSessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// Set up the realm.
securityManager.setRealm(myShiroRealm());
// Inject the cache manager ;
securityManager.setCacheManager(cacheManager);// And this is the same thing if you execute it multiple times 1 An object ;
// session manager
securityManager.setSessionManager(webSessionManager);
// Inject Remember Me Manager ;
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
The test results are as follows:
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
===============update================
==============doReadSession=================
==============doReadSession=================
===============update================
==============doReadSession=================
==============doReadSession=================
==============doReadSession=================
Permission configuration --
>
MyShiroRealm.doGetAuthorizationInfo()
==============doReadSession=================
We will find that, when there are multiple resources in a page, will keep calling doReadSession, update method to read and update session, at present, this problem has not thought of a better solution.