美文网首页我爱编程
Spring集成shiro使用redis管理session

Spring集成shiro使用redis管理session

作者: 不敢预言的预言家 | 来源:发表于2018-03-25 16:10 被阅读0次

    接管shiro的缓存只需要重写SessionDAO实现。

    spring-shrio.xml相关配置

    <!--session操作-->
        <bean id="shiroRedisSessionDAO" class="com.sdhs.mob.common.shiro.ShiroRedisSessionDAO">
            <constructor-arg ref="redisTemplate"/>
            <property name="sessionIdGenerator">
                <bean class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
            </property>
        </bean>
    
    <!--session管理器-->
        <bean id="shiroRedisSessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
            <property name="sessionDAO" ref="shiroRedisSessionDAO"/>
            <!--超时 ms-->
            <property name="globalSessionTimeout" value="1800000"/>
            <!-- 相隔多久检查一次session的有效性   -->
            <property name="sessionValidationInterval" value="900000"/>
            <!-- 删除失效session -->
            <property name="deleteInvalidSessions" value="true"/>
        </bean>
    
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <!--单个realm使用realm,如果有多个realm,使用realms属性代替 -->
            <property name="realm" ref="shiroRealm"/>
            <!-- 使用session管理器 -->
            <property name="sessionManager" ref="shiroRedisSessionManager"/>
        </bean>
    

    这里的sessionManager使用的默认的 DefaultWebSessionManager,只重写了sessionDAO实现


    ShiroRedisSessionDAO

    ShiroRedisSessionDAO.java

    package com.sdhs.mob.common.shiro;
    
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.UnknownSessionException;
    import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    
    import java.io.Serializable;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    /**
     * shiro redis session
     *
     * @author seer
     * @date 2018/3/25 10:38
     */
    public class ShiroRedisSessionDAO extends AbstractSessionDAO {
        private static Logger LOGGER = LogManager.getLogger(ShiroRedisSessionDAO.class);
        /**
         * key前缀
         */
        private static final String SHIRO_REDIS_SESSION_KEY_PREFIX = "shiro.redis.session_";
    
        private RedisTemplate redisTemplate;
    
        private ValueOperations valueOperations;
    
        public ShiroRedisSessionDAO(RedisTemplate redisTemplate) {
            this.redisTemplate = redisTemplate;
            this.valueOperations = redisTemplate.opsForValue();
        }
    
        @Override
        protected Serializable doCreate(Session session) {
            Serializable sessionId = this.generateSessionId(session);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("shiro redis session create. sessionId={}", sessionId);
            }
            this.assignSessionId(session, sessionId);
            valueOperations.set(generateKey(sessionId), session, session.getTimeout(), TimeUnit.MILLISECONDS);
            return sessionId;
        }
    
        @Override
        protected Session doReadSession(Serializable sessionId) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("shiro redis session read. sessionId={}", sessionId);
            }
            return (Session) valueOperations.get(generateKey(sessionId));
        }
    
        @Override
        public void update(Session session) throws UnknownSessionException {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("shiro redis session update. sessionId={}", session.getId());
            }
            valueOperations.set(generateKey(session.getId()), session, session.getTimeout(), TimeUnit.MILLISECONDS);
        }
    
        @Override
        public void delete(Session session) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("shiro redis session delete. sessionId={}", session.getId());
            }
            redisTemplate.delete(generateKey(session.getId()));
        }
    
        @Override
        public Collection<Session> getActiveSessions() {
            Set<Object> keySet = redisTemplate.keys(generateKey("*"));
            Set<Session> sessionSet = new HashSet<>();
            if (CollectionUtils.isEmpty(keySet)) {
                return Collections.emptySet();
            }
            for (Object key : keySet) {
                sessionSet.add((Session) valueOperations.get(key));
            }
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("shiro redis session all. size={}", sessionSet.size());
            }
            return sessionSet;
        }
    
        /**
         * 重组key
         * 区别其他使用环境的key
         *
         * @param key
         * @return
         */
        private String generateKey(Object key) {
            return SHIRO_REDIS_SESSION_KEY_PREFIX + this.getClass().getName() +"_"+ key;
        }
    }
    

    这里使用的redisTemplate操作redis,直接使用redisConnection操作redis可以参考:Spring中使用Redis做为Mybatis二级缓存


    直接实现CachingSessionDAO可以最快的实现redis管理session

    ShiroRedisCacheSessionDAO.java

    package com.sdhs.mob.common.shiro;
    
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.eis.CachingSessionDAO;
    
    import java.io.Serializable;
    
    /**
     * ShiroRedisCacheSessionDAO
     *
     * @author seer
     * @date 2018/3/25 16:03
     */
    public class ShiroRedisCacheSessionDAO extends CachingSessionDAO {
        @Override
        protected void doUpdate(Session session) {
            this.getCacheManager().getCache(this.getClass().getName()).put(session.getId(), session);
        }
    
        @Override
        protected void doDelete(Session session) {
            this.getCacheManager().getCache(this.getClass().getName()).remove(session.getId());
        }
    
        @Override
        protected Serializable doCreate(Session session) {
            Serializable sessionId = this.generateSessionId(session);
            this.assignSessionId(session, sessionId);
            this.getCacheManager().getCache(this.getClass().getName()).put(session.getId(), session);
            return sessionId;
    
        }
    
        @Override
        protected Session doReadSession(Serializable sessionId) {
            return (Session) this.getCacheManager().getCache(this.getClass().getName()).get(sessionId);
        }
    }
    

    需要配置好cacheManager,参考文档:Spring集成shiro使用redis做缓存


    shiro获取session,一次请求多次获取的问题可以参考:shiro 使用redis 频繁请求获取session的问题

    相关文章

      网友评论

        本文标题:Spring集成shiro使用redis管理session

        本文链接:https://www.haomeiwen.com/subject/oxrccftx.html