spring boot統合redisを統合して、shiroの分散式session共有を実現する方法


ShroはSession ManagerでSessionを管理していますが、Sessionの操作はSessionDaoで行われています。デフォルトでは、Shroは2つのSession Daoを実現しています。それぞれCachingSession DAOとMemorySession DAOです。EhCacheを使って保存する場合は、Cachinaのキャッシュが適用されません。メモリベースのSessionDaoを選択します。だから、Redisベースの分布式Session共有を実現するには、Session Managerの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をSession Managerに追加する必要があります。コードは以下の通りです。

 @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; 
  } 
最後のステップはSession Managerを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======================================================================== 
=========udate========================================================================= 
=========doReadSession======================================================================== 
=========doReadSession======================================================================== 
=========udate========================================================================= 
=========doReadSession======================================================================== 
=========doReadSession======================================================================== 
=========doReadSession======================================================================== 
権限構成-->MyShiroRealm.doGetAuthoriationInfo() 
=========doReadSession======================================================================== 
私たちは一つのページに複数のリソースが存在する場合、doReadSessionを呼び起こし、udate方法でsessionを読み込み、更新することができます。現在この問題はまだ考えられていません。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。