• shiro-会话管理(session管理)


    shiro-会话管理(session管理)

    shiro自己实现了一套session管理体系可以在不借助任何web容器或servlet的情况下使用session。
    1.SessionManager(session管理器)、SessionDAO(实现session的增删改查)
    2.Redis实现Session共享
    3.Redis实现Session共享存在的问题
    代码:
    pom.xml文件中添加依赖

        
                    redis.client
                    jedis
                    2.8.0
        
    
    • 1
    • 2
    • 3
    • 4
    • 5

    通过jedis来实现session共享主要是重写他的一些增删改查方法,主要是通过重写AbstractSessionDAO的一些方法,我们新建自己的dao,新建session.RedisSessionDao.java。

    package com.imooc.session;
    
    import com.imooc.Util.JedisUtil;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.UnknownSessionException;
    import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
    import org.apache.shiro.util.CollectionUtils;
    import org.springframework.util.SerializationUtils;
    
    import javax.annotation.Resource;
    import java.io.Serializable;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.Set;
    
    public class RedisSessionDao extends AbstractSessionDAO{
    
        @Resource
        private JedisUtil jedisUtil;
    
        private final  String SHIRO_SESSION_PREFIX = "imooc_session";
    
        /*key由sessionid和前缀SHIRO_SESSION_PREFIX组成 二进制方式返回*/
        private byte[] getKey(String key){
            return (SHIRO_SESSION_PREFIX+key).getBytes();
        }
    
        /*保存session*/
        private void saveSession(Session session){
            if (session!=null&&session.getId()!=null){
                byte[] key = getKey(session.getId().toString());
                /*将session序列化*/
                byte[] value = SerializationUtils.serialize(session);
                jedisUtil.set(key,value);
                /*设置超时时间*/
                jedisUtil.expire(key,600);
            }
    
        }
    
        @Override
        protected Serializable doCreate(Session session) {
            /*通过sessionId保存对应的session*/
            Serializable sessionId = generateSessionId(session);
            /*将sessionId和session捆绑*/
            assignSessionId(session,sessionId);
           saveSession(session);
            return sessionId;
        }
    
        /**
         * 通过sessionId获得session
         * @param sessionId
         * @return
         */
        @Override
        protected Session doReadSession(Serializable sessionId) {
            if (sessionId==null){
                return null;
            }
            byte[] key = getKey(sessionId.toString());
            byte[] value = jedisUtil.get(key);
            //将值反序列化为session对象
            return (Session) SerializationUtils.deserialize(value);
        }
    
        public void update(Session session) throws UnknownSessionException {
           saveSession(session);
    
        }
    
        public void delete(Session session) {
    
            if(session==null||session.getId()==null){
                return;
            }
            byte[] key = getKey(session.getId().toString());
            jedisUtil.del(key);
        }
    
        /*获得指定的存活的session*/
        public Collection getActiveSessions() {
            /*通过前缀获得相关的所有的key*/
            Set keys = jedisUtil.getKeys(SHIRO_SESSION_PREFIX);
            Set sessions = new HashSet();
            if (CollectionUtils.isEmpty(keys)){
                return sessions;
            }
            for(byte[] key: keys){
                //反序列化为session对象
                Session session = (Session) SerializationUtils.deserialize(jedisUtil.get(key));
                sessions.add(session);
            }
    
            return sessions;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    创建一个Redis访问的工具包,新建utils.JedisUtil.java

    package com.imooc.Util;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    
    import javax.annotation.Resource;
    import java.util.Set;
    
    
    /**
     * 写Jedis操作的一些方法
     */
    @Component
    public class JedisUtil {
    
        /**
         * JedisPool连接池,用于获取连接
         */
       @Autowired
       private JedisPool jedisPool;
    
        private Jedis getResources(){
            return jedisPool.getResource();
        }
    
    
        public byte[] set(byte[] key, byte[] value) {
    
            Jedis jedis = jedisPool.getResource();
            try{
                jedis.set(key,value);
                return value;
            }finally {
                jedis.close();
            }
    
        }
    
        /*设置指定key的超时时间,单位为s*/
        public void expire(byte[] key, int i) {
            Jedis jedis = jedisPool.getResource();
            try{
                jedis.expire(key,i);
            }finally {
                jedis.close();
            }
        }
    
        public byte[] get(byte[] key) {
            Jedis jedis = jedisPool.getResource();
            try{
                return jedis.get(key);
            }finally {
                jedis.close();
            }
        }
    
        public void del(byte[] key) {
            Jedis jedis = jedisPool.getResource();
            try{
                jedis.del(key);
            }finally {
                jedis.close();
            }
        }
    
        public Set getKeys(String shiro_session_prefix) {
            Jedis jedis = jedisPool.getResource();
            try{
                return jedis.keys((shiro_session_prefix+"*").getBytes());
            }finally {
                jedis.close();
            }
        }
    }
    
    ```创建Redis相关的spring文件,通过构造器的方式来创建。
    spring-redis.xml
    ```xml
    
    
    
        
            
            
            
        
    
        
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    这样我们的JedisPool就创建成功了,我们在JedisUtils里引入。
    在spring.xml文件里引入spring-redis.xml。

    
    
    • 1

    将JedisUtil注入RedisSessionDao中,

    @Resource
        private JedisUtil jedisUtil;
    
    • 1
    • 2

    小记:注入就是spring的管理机制bean工厂已经把对象及其属性创建好,只需要程序员去调用。关于spring注入的方式,引用一下一位大佬的博客。https://blog.csdn.net/a909301740/article/details/78379720

    RedisSessionDao重写AbstractSessionDao的详细方法我们卸载JedisUtils里。
    ++++++我是分割线----进入第二部分啦+++
    在spring.xml里配置sessionManager

    
            
        
    
        
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在securityManager中加入sessionManager属性

    
    
    • 1

    因为DefaultWebSessionManager会重复多次读取session浪费资源,所以我们重写一下DefaultWebSessionManager的retrieveSession方法
    CustomSessionManager.java

    package com.imooc.session;
    
    import com.sun.xml.internal.ws.developer.Serialization;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.UnknownSessionException;
    import org.apache.shiro.session.mgt.SessionKey;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.apache.shiro.web.session.mgt.WebSessionKey;
    import org.apache.shiro.web.session.mgt.WebSessionManager;
    import org.omg.CORBA.ServerRequest;
    
    import javax.servlet.ServletRequest;
    import java.io.Serializable;
    
    public class CustomSessionManager extends DefaultWebSessionManager{
    
        @Override
        protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
            Serializable sessionId = getSessionId(sessionKey);
            ServletRequest request = null;
            if (sessionKey instanceof WebSessionKey){
                request = (ServletRequest) ((WebSessionKey) sessionKey).getServletRequest();
            }
            if (request!=null&&sessionId!=null) {
                Session session = (Session) request.getAttribute(sessionId.toString());
                if(session!=null)
                {
                    return session;
                }
            }
           Session session = super.retrieveSession(sessionKey);
            if(request!=null &&sessionId!=null){
                request.setAttribute(sessionId.toString(),session);
            }
            return session;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    字符串 - string(Lua)
    vant-list上滑加载,数据重复,加载后返回顶部
    《算法基础》基础数据结构
    感受野计算问题
    JAVA:实现Disjoint Sets不相交集合算法(附完整源码)
    想要精通算法和SQL的成长之路 - 摩尔投票法的运用
    DFT compiler极简示例2(使用autofix)
    Python标准库sys
    多色柱状图让数据区分更明显更醒目
    盲水印添加,获取接口
  • 原文地址:https://blog.csdn.net/egegerhn/article/details/126496208