使用Shiro重写Session

先看下我们的基本用法:

@RequestMapping("/index")
public ModelAndView index(HttpSession session){
    System.out.println(session.getId());
    ModelAndView modelAndView = new ModelAndView("main/index");
    return modelAndView;
}

如果我们添加断点进行调试,可以看到session类型是:

org.apache.catalina.session.StandardSessionFacade

依赖于tomcat容器。

Shiro是一款非常优秀的用户-角色-权限管理框架,具体可以Google下。当然,Shiro也提供Session管理模块,现在我们就使用shiro+spring实现一个与容器无关的session。

  1. 引入shiro的jar包
  2. <properties>
        <shiroVersion>1.2.3</shiroVersion>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiroVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>${shiroVersion}</version>
        </dependency>
    
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>${shiroVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiroVersion}</version>
        </dependency>
    </dependencies>
  3. 配置shiro(web.xml)
  4. <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
  5. 配置shiro(spring)
  6. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="sessionManager" ref="sessionManager"/>
    </bean>
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
    </bean>
    <bean id="sessionManager" class="com.whereta.model.DemoSessionManager">
        <property name="globalSessionTimeout" value="1000" />
        <property name="deleteInvalidSessions" value="true" />
        <property name="sessionValidationSchedulerEnabled" value="false" />
        <property name="sessionDAO" ref="sessionDao" />
    </bean>
    <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator" />
    <bean id="demoCache" class="com.whereta.model.DemoCache" />
    <bean id="sessionDao" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
        <property name="sessionIdGenerator" ref="sessionIdGenerator" />
        <property name="activeSessionsCache" ref="demoCache"/>
    </bean>
  7. 具体类用法
  8. package com.whereta.model;
    
    import org.apache.shiro.cache.Cache;
    import org.apache.shiro.cache.CacheException;
    import org.apache.shiro.session.Session;
    
    import java.io.Serializable;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * 该类是缓存工具类,提供session的存储和获取等方法
     * @author Vincent
     * @time 2015/7/27 15:00
     */
    public class DemoCache implements Cache<Serializable, Session> {
        //模拟缓存存储session对象
        private static final Map<Serializable, Session> map = new HashMap<Serializable, Session>();
    
        public Session get(Serializable key) throws CacheException {
            //根据key获取缓存中的session
            return map.get(key);
        }
    
        public Session put(Serializable key, Session value) throws CacheException {
            //将session对象存入缓存
            map.put(key, value);
            return value;
        }
    
        public Session remove(Serializable key) throws CacheException {
            //移除session中为key的对象
            Session session = get(key);
            if (session != null) {
                session.setAttribute(key, null);
                return session;
            }
            return null;
        }
    
        public void clear() throws CacheException {
            //清除所有的session
            map.clear();
        }
    
        public int size() {
            //返回session的数量
            return map.size();
        }
    
        public Set<Serializable> keys() {
            //返回所有session的key
            return map.keySet();
        }
    
        public Collection<Session> values() {
            //返回所有session
            return map.values();
        }
    }
  9. package com.whereta.model;
    
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
    
    import java.io.Serializable;
    
    /**
     * sessionId生成工具类
     * @author Vincent
     * @time 2015/7/27 11:45
     */
    public class DemoSessionIdGenerator implements SessionIdGenerator {
    
        public Serializable generateId(Session session) {
            //自定义规则生成sessionid
            return System.currentTimeMillis();
        }
    }
  10. package com.whereta.model;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.SessionContext;
    import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.apache.shiro.web.util.WebUtils;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import java.io.Serializable;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 集成websession管理器,重写两个方法实现自己的需求
     * @author Vincent
     * @time 2015/7/27 15:35
     */
    public class DemoSessionManager extends DefaultWebSessionManager {
        //自定义缓存,存储  客户端-sessionid
        public static final Map<String,Serializable> MAP=new HashMap<String, Serializable>();
    
        private static Log log = LogFactory.getLog(DemoSessionManager.class);
        @Override
        protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
            HttpServletRequest req= (HttpServletRequest) request;
            //假设以请求地址为key标注唯一一个客户端
            String remoteHost = req.getRemoteHost();
            //存入缓存
            Serializable id = MAP.get(remoteHost);
            return id;
        }
    
        @Override
        protected void onStart(Session session, SessionContext context) {
            //判断是否是http请求
            if (!WebUtils.isHttp(context)) {
                log.debug("SessionContext argument is not HTTP compatible or does not have an HTTP request/response " +
                        "pair. No session ID cookie will be set.");
                return;
    
            }
            HttpServletRequest request = WebUtils.getHttpRequest(context);
            request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
            String remoteHost = request.getRemoteHost();
            Serializable id = session.getId();
            MAP.put(remoteHost,id);
        }
    }

    通过以上配置,可以再次运行查看session,已经变为shiro的自定义session了

  11. org.apache.shiro.web.servlet.ShiroHttpSession
时间: 2024-08-12 21:08:01

使用Shiro重写Session的相关文章

Shiro - 关于session

Shiro Session session管理可以说是Shiro的一大卖点. Shiro可以为任何应用(从简单的命令行程序还是手机应用再到大型企业应用)提供会话解决方案. 在Shiro出现之前,如果我们想让你的应用支持session,我们通常会依赖web容器或者使用EJB的Session Bean. Shiro对session的支持更加易用,而且他可以在任何应用.任何容器中使用. 即便我们使用Servlet或者EJB也并不代表我们必须使用容器的session,Shiro提供的一些特性足以让我们用

springboot shiro 前后端分离,解决跨域、过虑options请求、shiro管理session问题、模拟跨域请求

一.解决跨域.过虑options请求问题 1.创建过虑类 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; im

php重写session的存储机制

重写session的存储机制 Session数据区 默认以 文件的形式存储与服务器操作系统临时目录中! 当 session数据区过多时,文件形式的存储,操作速度变慢.磁盘的读写(IO,input/output)开销是很大的. 实际项目中,都会采用其他的方式更快地存储session数据.典型的办法:数据库,内存. 以 数据库存储为例,讲解:session数据入库! 重写 与 session数据区直接的相关操作即可: 最基本的只有2个:读,写! 一:定义2个可以完成读和写的函数. 二:告知sessi

使用redis进行基于shiro的session集群共享

之前写过一篇nginx多tomcat负载均衡,主要记录了使用nginx对多个tomcat 进行负载均衡,其实进行负载均衡之前还有一个问题没有解决,那就是集群间的session共享,不然用户在登录网站之后session保存在tomcat A,但是下次访问的时候nginx分发到了tomcat B,这个时候tomcat B没有刚刚用户登录的session,所以用户就失去了(本次)登录状态,下次访问的时候nginx可能又分发到了tomcat A(其实通过配置可以给各个服务器分配权重,nginx根据权重来

Shiro 设置session超时时间

通过api:Shiro的Session接口有一个setTimeout()方法 //登录后,可以用如下方式取得session SecurityUtils.getSubject().getSession().setTimeout(30000); 查看Shiro的api文档, setTimeout void setTimeout(long maxIdleTimeInMillis) throws InvalidSessionExceptionSets the time in milliseconds t

shiro实现session共享

session共享:在多应用系统中,如果使用了负载均衡,用户的请求会被分发到不同的应用中,A应用中的session数据在B应用中是获取不到的,就会带来共享的问题. 假设:用户第一次访问,连接的A服务器,进行了登录操作进入了系统,当用户再次操作时,请求被转发到了B服务器,用户并没有在B进行登录,此时用户又来到了登录页面,这是难以理解和接受的,这就引出了session共享. 对于shiro框架如何实现session的共享呢?shiro的共享分为两个方面,一个是session的共享,一个是cache的

jsp输出shiro中session信息

一.引用shiro标签 jsp页面头部引用<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>标签 二.shiro中存放的是用户名等字符串: <shiro:principal/> 三.shiro中存放的是用户对象,property是对象里面的属性,相当于user.getUserName() <shiro:principal property="userN

Apache shiro集群实现 (六)分布式集群系统下的高可用session解决方案---Session共享

Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro Authentication) Apache shiro集群实现 (四)shiro授权(Authentication)--访问控制 Apache shiro集群实现 (五)分布式集群系统下的高可用session解决方案 Apache shiro集群实现 (六)分布式集群系统下的高可用session

Shiro源码分析之两种Session的方式

1.Shiro默认的Session处理方式 <!-- 定义 Shiro 主要业务对象 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- <property name="sessionManager" ref="sessionManager" />