zoukankan      html  css  js  c++  java
  • shiro的session管理

    shiro的SessionManager

    在官方架构图里面:
    在这里插入图片描述
    在默认的SecurityManager的uml图里面:
    在这里插入图片描述
    前面的CacheSecurityManager,realmSecurityManager,认证管理器,鉴权管理器都讲过了,那么这个Session管理器是怎么回事呢?

    在web容器里面的session跟HttpSession是同一个吗?

    首先看,我们在没有设置Session管理器的时候,默认使用的是哪一个?
    先看SessionManager的具体实现:
    在这里插入图片描述
    第一个类是AbstractNativeSessionManager,是个抽象类,主要实现就是DefaultSessionManager跟DefaultWebSessionManager,而DefaultWebSessionManager又是继承了DefaultSessionManager,我们看一下DefaultWebSessionManager的uml图:
    在这里插入图片描述
    WebSessionManager里面就一个方法isServletContainerSessions判断是否是本地会话,就是相当于判断是不是httpSession.
    再看SessionsSecurityManager,直接看我们使用的webSecurityManager:
    在这里插入图片描述
    ServletContainerSessionManager就相当于是使用HttpSession:ServletContainerSessionManager的createSession方法返回的是HttpServletSession,而HttpServletSession内部是直接维护了HttpSession对象,然后一系列方法是直接使用HttpSession进行操作的:
    在这里插入图片描述
    在这里插入图片描述

    自定义sessionManager

    看看ServletContainerSessionManager和DefaultWebSessionManager一起的uml图:
    在这里插入图片描述
    默认的是使用的ServletContainerSessionManager,如果我们想自定义,就直接使用DefaultWebSessionManager即可了;DefaultWebSessionManager需要设置的属性主要有:

    • SessionListener,session监听
    • setSessionDAO设置sessionDao,session缓存,或者持久化
    • sessionIdCookie设置cookie
    • setGlobalSessionTimeout全局会话超时时间
    • setDeleteInvalidSessions是否删除无效session,默认true
    • setSessionValidationSchedulerEnabled定时删除,默认true
    • setSessionValidationInterval设置多长时间检测一下是否有过期session.然后删除
    • setSessionIdUrlRewritingEnabled是否开启url后面加上sessionId

    我们先看SessionDAO

    sessionDao就是一系列的操作session的接口:
    在这里插入图片描述
    看实现:
    在这里插入图片描述
    抽象的就不看了,就三个具体实现:EnterpriseCacheSessionDAO,MemorySessionDAO,RedisSessionDAO,RedisSessionDAO就不说了比较简单,前面说shiro使用redis缓存的时候也说过了,这个那就是session缓存在redis里面,MemorySessionDAO也是,内部维护了一个ConcurrentMap来保存session,就是内存缓存了;EnterpriseCacheSessionDAO就是可以自己传一个CacheManager,好比ehcache的manager,然后就将缓存存在ehcache也可以直接传个内存缓存,也就放在内存里面了,也可以自定义sessionid的生成器,默认是JavaUuidSessionIdGenerator也就是uuid,可以自己实现.

    使用内存缓存

    直接使用MemorySessionDAO:

        @Bean
        public SessionDAO sessionDAO() {
    
            return new MemorySessionDAO();
            }
    

    使用ehcache

            // ehcache
                public SessionDAO sessionDAO() {
    
            EnterpriseCacheSessionDAO enterpriseCacheSessionDAO = new EnterpriseCacheSessionDAO();
            EhCacheManager ehCacheManager = new EhCacheManager();
            ehCacheManager.setCacheManager(getEhCacheManager());
            enterpriseCacheSessionDAO.setCacheManager(ehCacheManager);
            enterpriseCacheSessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
            enterpriseCacheSessionDAO.setSessionIdGenerator(new JavaUuidSessionIdGenerator());
            return enterpriseCacheSessionDAO;
            }
    

    使用redis

    org.crazycake.shiro.RedisSessionDAO的包注意:

      public SessionDAO sessionDAO() {
      
            //redis
            RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
            RedisManager redisManager = new RedisManager();
            redisSessionDAO.setRedisManager(redisManager);
            return redisSessionDAO;
    
        }
    

    剩下的配置比较简单:

        /**
         * 配置会话管理器,设定会话超时及保存
         * @return
         */
        @Bean
        public SessionManager sessionManager() {
            DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
            Collection<SessionListener> listeners = new ArrayList<SessionListener>();
            //配置监听
            listeners.add(new ShiroSessionListener());
            sessionManager.setSessionListeners(listeners);
            sessionManager.setSessionIdCookie(sessionIdCookie());
            sessionManager.setSessionDAO(sessionDAO());
            sessionManager.setCacheManager(new MemoryConstrainedCacheManager());
    
            sessionManager.setGlobalSessionTimeout(10000);
            sessionManager.setDeleteInvalidSessions(true);
            sessionManager.setSessionValidationSchedulerEnabled(true);
            sessionManager.setSessionValidationInterval(5000);
            sessionManager.setSessionIdUrlRewritingEnabled(false);
    
            return sessionManager;
        }
    
      @Bean("sessionIdCookie")
        public SimpleCookie sessionIdCookie(){
            SimpleCookie simpleCookie = new SimpleCookie("sid");
            simpleCookie.setHttpOnly(true);
            simpleCookie.setPath("/");
            //maxAge=-1表示浏览器关闭时失效此Cookie
            simpleCookie.setMaxAge(-1);
            return simpleCookie;
        }
    
    

    需要自己实现session监听:

    public interface SessionListener {
        void onStart(Session var1);
    
        void onStop(Session var1);
    
        void onExpiration(Session var1);
    }
    

    记录人数的:

    public class ShiroSessionListener implements SessionListener {
    
        /**
         * 统计在线人数
         * juc包下线程安全自增
         */
        private final AtomicInteger sessionCount = new AtomicInteger(0);
    
        /**
         * 会话创建时触发
         * @param session
         */
        @Override
        public void onStart(Session session) {
            //会话创建,在线人数加一
            sessionCount.incrementAndGet();
        }
    
        /**
         * 退出会话时触发
         * @param session
         */
        @Override
        public void onStop(Session session) {
            //会话退出,在线人数减一
            sessionCount.decrementAndGet();
        }
    
        /**
         * 会话过期时触发
         * @param session
         */
        @Override
        public void onExpiration(Session session) {
            //会话过期,在线人数减一
            sessionCount.decrementAndGet();
        }
        /**
         * 获取在线人数使用
         * @return
         */
        public AtomicInteger getSessionCount() {
            return sessionCount;
        }
    }
    

    总结

    这里是web的session简单用法,如果是java环境,那么session就比较简单了,前面都有分析到.不过现在一般都不使用session了,所以这一块,只需要知道就好了,现在项目一般都是有app端的,集群的,多应用共享的,就是单点登录这样的.所以基于传统的session已经很难实现需求了,解决方案一般是shiro+jwt基于token方式实现.后期会讲到

    世界上所有的不公平都是由于当事人能力不足造成的.
  • 相关阅读:
    关于 Blog 修改
    How To Manage StartUp Applications In Ubuntu
    C++11 之for 新解 auto
    How To Install Cacti On Ubuntu 14
    Apache 2 解析html中的php
    Raspberry Pi
    Compiling a kernel module for the raspberry pi 2 via Ubuntu host
    ubuntu 14.04/14.10 iptables 防火墙设置
    ajax概述
    ajax 异步 通信 小例子 servlet与 jsp异步 post方法
  • 原文地址:https://www.cnblogs.com/javayida/p/13346777.html
Copyright © 2011-2022 走看看