使用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

转载于:https://my.oschina.net/vincentzhao/blog/484341

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shiro 中,SessionManager 负责管理用户的会话信息,其主要职责包括创建、获取、删除和管理会话等。下面是一个简单的 Shiro SessionManager 的配置示例: ```xml <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- session过期时间,单位:毫秒 --> <property name="globalSessionTimeout" value="1800000" /> <!-- 是否开启URL地址栏中的SessionID重写 --> <property name="sessionIdUrlRewritingEnabled" value="false" /> <!-- 是否开启删除无效的session对象 --> <property name="deleteInvalidSessions" value="true" /> <!-- 是否开启定时调度器检测失效的session对象 --> <property name="sessionValidationSchedulerEnabled" value="true" /> <!-- 定时清理失效session的时间间隔,单位:毫秒;默认1小时 --> <property name="sessionValidationInterval" value="3600000" /> <!-- 会话DAO --> <property name="sessionDAO" ref="redisSessionDAO" /> </bean> ``` 其中,`DefaultWebSessionManager` 是 Shiro 默认提供的 Web 环境下的 SessionManager 实现类,我们可以通过配置它的属性来实现相关功能。具体的属性含义如下: - `globalSessionTimeout`:会话超时时间,单位为毫秒,默认为30分钟。 - `sessionIdUrlRewritingEnabled`:是否在URL地址栏中重写Session ID,默认为false,建议不开启,因为这会让URL泄漏了Session ID,存在安全风险。 - `deleteInvalidSessions`:是否开启删除无效Session对象,默认为true,表示当Session超时或者被踢出时自动删除相应的Session对象。 - `sessionValidationSchedulerEnabled`:是否开启定时调度器检测失效的Session对象,默认为true,表示在应用启动时会启动一个定时任务,定期检测失效的Session并删除它们。 - `sessionValidationInterval`:定时清理失效Session的时间间隔,单位为毫秒,默认为1小时。 - `sessionDAO`:指定会话DAO,即会话的存储方式。这里我们使用 Redis 作为会话存储方式,所以指定了 `redisSessionDAO`。 需要注意的是,如果要使用 Redis 作为会话存储方式,还需要配置相应的 `redisSessionDAO`。具体的配置可以参考下面的示例: ```xml <bean id="redisSessionDAO" class="org.crazycake.shiro.RedisSessionDAO"> <!-- 配置RedisManager --> <property name="redisManager" ref="redisManager" /> <!-- session在Redis中的过期时间,单位是秒 --> <property name="expire" value="1800" /> </bean> <bean id="redisManager" class="org.crazycake.shiro.RedisManager"> <!-- Redis服务器地址,格式为:host:port --> <property name="host" value="127.0.0.1:6379" /> <!-- Redis服务器连接超时时间,单位为毫秒,默认为2000ms --> <property name="timeout" value="2000" /> <!-- Redis服务器密码,如果没有设置可以不填 --> <property name="password" value="your_password" /> <!-- Redis数据库编号,默认为0 --> <property name="database" value="0" /> </bean> ``` 其中,`RedisSessionDAO` 是一个实现了 Shiro `SessionDAO` 接口的 Redis Session 存储类。`RedisManager` 则是一个 Redis 连接管理类,用于管理与 Redis 服务器的连接。需要注意的是,上面的 `redisSessionDAO` 和 `redisManager` 需要通过 Spring 容器进行管理,所以需要在 Spring 配置文件中进行相应的配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值