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.


Related articles: