shirocas怎么做session共享redis tomcat

2024-12-22 10:23:02
推荐回答(1个)
回答1:

  1. 第一步:配置WEB.XML

       shiroFilter
       org.springframework.web.filter.DelegatingFilterProxy
       
           targetFilterLifecycle
           true
       



       shiroFilter
       /*

    第二步:SHIRO整合SPRING配置
    applicationContext-shiro.xml 伪代码:



       
       
       
       
       




       



         class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler">
       
       




       
           
       
       
       




       ...
       

    第三步:Zookeeper对Shiro-SessionDao实现类
    ZKShiroSessionDAO.JAVA伪代码:

    import bgonline.foundation.hadoop.zk.IZookeeperTemplate;
    import bgonline.foundation.hadoop.zk.ZNode;
    import org.apache.shiro.cache.AbstractCacheManager;
    import org.apache.shiro.cache.Cache;
    import org.apache.shiro.cache.CacheException;
    import org.apache.shiro.cache.MapCache;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.UnknownSessionException;
    import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
    import org.apache.shiro.session.mgt.eis.CachingSessionDAO;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.util.SerializationUtils;

    import java.io.Serializable;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;

    /**
    * ZOOKEEPER实现SHIRO集群SESSION存储
    *
    * @author aliencode
    * @date 13-7-10
    */
    public class ZKShiroSessionDAO extends CachingSessionDAO {

       public ZKShiroSessionDAO() {
       }

       private boolean useMemCache = false;

       /**
        * SESSION ZK DAO 实例
        * 如果开户缓存
        * 用户登录时自动缓存, 用户登录超时自动删除
        * 由于shiro的cacheManager是全局的, 所以这里使用setActiveSessionsCache直接设置Cache来本地缓存, 而不使用全局zk缓存.
        * 由于同一用户可能会被路由到不同服务器,所以在doReadSession方法里也做了缓存增加.
        *
        * @param useMemCache 是否使用内存缓存登录信息
        */
       public ZKShiroSessionDAO(boolean useMemCache) {
           this.useMemCache = useMemCache;
           if (useMemCache) {
               setActiveSessionsCache(
                       new MapCache<>(this.ACTIVE_SESSION_CACHE_NAME, new ConcurrentHashMap())
               );
           }
       }

       Logger logger = LoggerFactory.getLogger(this.getClass());

       /**
        * ZK操作类
        */
       private IZookeeperTemplate zookeeperTemplate;

       /**
        * 缓存根路径, 结尾不加/
        */
       private String shiroSessionZKPath = "/SHIROSESSIONS";

       /**
        * 缓存项前缀
        */
       private String sessionPrefix = "session-";

       /**
        * 设置Shiro Session 前缀 默认 session-
        *
        * @param sessionPrefix
        */
       public void setSessionPrefix(String sessionPrefix) {
           this.sessionPrefix = sessionPrefix;
       }

    public void setZookeeperTemplate(IZookeeperTemplate zookeeperTemplate) {
           this.zookeeperTemplate = zookeeperTemplate;
       }

       /**
        * 设置Shiro在ZK服务器存放根路径
        *
        * @param shiroSessionZKPath 默认值:/SHIROSESSIONS/
        */
       public void setShiroSessionZKPath(String shiroSessionZKPath) {
           this.shiroSessionZKPath = shiroSessionZKPath;
       }

       /**
        * session更新
        *
        * @param session
        * @throws UnknownSessionException
        */
       @Override
       public void update(Session session) throws UnknownSessionException {
           if (session == null || session.getId() == null) {
               logger.error("session argument cannot be null.");
           }
           saveSession(session, "update");
       }

       @Override
       protected void doUpdate(Session session) {
       }

       /**
        * session删除
        *
        * @param session
        */
       @Override
       public void delete(Session session) {
           if (session == null || session.getId() == null) {
               logger.error("session argument cannot be null.");
           }
           logger.debug("delete session for id: {}", session.getId());
           zookeeperTemplate.deleteNode(getPath(session.getId()));
           if (useMemCache) {
               this.uncache(session);
           }
       }

       @Override
       protected void doDelete(Session session) {
       }

       /**
        * 获取当前活跃的session, 当前在线数量
        *
        * @return
        */
       @Override
       public Collection getActiveSessions() {
           ZNode zNode = new ZNode();
           zNode.setPath(shiroSessionZKPath);
           Set sessions = new HashSet();
           //读取所有SessionID  , 返回形如: session-9e3b5707-fa80-4d32-a6c9-f1c3685263a5
           List ss = zookeeperTemplate.getChildren(zNode);
           for (String id : ss) {
               if (id.startsWith(sessionPrefix)) {
                   String noPrefixId = id.replace(sessionPrefix, "");
                   Session session = doReadSession(noPrefixId);
                   if (session != null) sessions.add(session);
               }
           }
           logger.debug("shiro getActiveSessions. size: {}", sessions.size());
           return sessions;
       }

       /**
        * 创建session, 用户登录
        *
        * @param session
        * @return
        */
       @Override
       protected Serializable doCreate(Session session) {
           Serializable sessionId = this.generateSessionId(session);
           this.assignSessionId(session, sessionId);
           saveSession(session, "create");
           return sessionId;
       }

       /**
        * session读取
        *
        * @param id
        * @return
        */
       @Override
       protected Session doReadSession(Serializable id) {
           if (id == null) {
               logger.error("id is null!");
               return null;
           }
           logger.debug("doReadSession for path: {}", getPath(id));

           Session session;
           byte[] byteData = zookeeperTemplate.getData(getPath(id)).getByteData();
           if (byteData != null && byteData.length > 0) {
               session = (Session) SerializationUtils.deserialize(byteData);
               if (useMemCache) {
                   this.cache(session, id);
                   logger.debug("doReadSession for path: {}, add cached !", getPath(id));
               }
               return session;
           } else {
               return null;
           }
       }

       /**
        * 生成全路径
        *
        * @param sessID
        * @return
        */
       private String getPath(Serializable sessID) {
           return shiroSessionZKPath + '/' + sessionPrefix + sessID.toString();
       }

       /**
        * session读取或更新
        *
        * @param session
        * @param act     update/save
        */
       private void saveSession(Session session, String act) {
           Serializable sessionId = session.getId();
           ZNode sessionNode = new ZNode();
           sessionNode.setByteData(SerializationUtils.serialize(session));
           sessionNode.setPath(getPath(sessionId));
           logger.debug("save session for id: {}, act: {}", sessionId, act);
           if (act == "update")
               zookeeperTemplate.setData(sessionNode);
           else
               zookeeperTemplate.createNode(sessionNode);
       }

    }