第十章 会话管理(五) 会话验证

Shiro 提供了会话验证调度器,用于定期的验证会话是否已过期,如果过期将停止会话;出于性能考虑,一般情况下都是获取会话时来验证会话是否过期并停止会话的;但是如在web环境中,如果用户不主动退出是不知道会话是否过期的,因此需要定期的检测会话是否过期,Shiro 提供了会话验证调度器SessionValidationScheduler来做这件事情。


可以通过如下ini配置开启会话验证:

sessionValidationScheduler=org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
sessionValidationScheduler.interval = 3600000
sessionValidationScheduler.sessionManager=$sessionManager
sessionManager.globalSessionTimeout=1800000
sessionManager.sessionValidationSchedulerEnabled=true
sessionManager.sessionValidationScheduler=$sessionValidationScheduler

sessionValidationScheduler : 会话验证调度器, sessionManager 默认就是使用ExecutorServiceSessionValidationScheduler,其使用JDK的ScheduledExecutorService进行定期调度并验证会话是否过期;

sessionValidationScheduler.interval:设置调度时间间隔,单位毫秒,默认就是1 小时;

sessionValidationScheduler.sessionManager:设置会话验证调度器进行会话验证时的会话管理器;

sessionManager.globalSessionTimeout:设置全局会话超时时间,默认30 分钟,即如果30分钟内没有访问会话将过期;

sessionManager.sessionValidationSchedulerEnabled:是否开启会话验证器,默认是开启的;

sessionManager.sessionValidationScheduler: 设置会话验证调度器,默认就是使用ExecutorServiceSessionValidationScheduler。


Shiro 也提供了使用Quartz会话验证调度器:

sessionValidationScheduler=org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler
sessionValidationScheduler.sessionValidationInterval = 3600000
sessionValidationScheduler.sessionManager=$sessionManager

使用时需要导入shiro-quartz依赖:

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>1.2.2</version>
</dependency>


如 上会话验证调度器实现都是直接调用AbstractValidatingSessionManager 的validateSessions方法进行验证,其直接调用SessionDAO 的getActiveSessions方法获取所有会话进行验证,如果会话比较多,会影响性能;可以考虑如分页获取会话并进行验证,如com.github.zhangkaitao.shiro.chapter10.session.scheduler.MySessionValidationScheduler:

//分页获取会话并验证
String sql = "select session from sessions limit ?,?";
int start = 0; //起始记录
int size = 20; //每页大小
List<String> sessionList = jdbcTemplate.queryForList(sql, String.class, start, size);
while(sessionList.size() > 0) {
for(String sessionStr : sessionList) {
try {
Session session = SerializableUtils.deserialize(sessionStr);
Method validateMethod =
ReflectionUtils.findMethod(AbstractValidatingSessionManager.class,
"validate", Session.class, SessionKey.class);
validateMethod.setAccessible(true);
ReflectionUtils.invokeMethod(validateMethod,
sessionManager, session, new DefaultSessionKey(session.getId()));
} catch (Exception e) {
//ignore
}
}
start = start + size;
sessionList = jdbcTemplate.queryForList(sql, String.class, start, size);
}

其直接改造自ExecutorServiceSessionValidationScheduler,如上代码是验证的核心代码,可以根据自己的需求改造此验证调度器器;ini的配置和之前的类似。


如果在会话过期时不想删除过期的会话,可以通过如下ini配置进行设置:

sessionManager.deleteInvalidSessions=false

默认是开启的,在会话过期后会调用SessionDAO的delete 方法删除会话:如会话时持久化存储的,可以调用此方法进行删除。


如果是在获取会话时验证了会话已过期,将抛出InvalidSessionException;因此需要捕获这个异常并跳转到相应的页面告诉用户会话已过期,让其重新登录,如可以在web.xml 配置相应的错误页面:

<error-page>
<exception-type>org.apache.shiro.session.InvalidSessionException</exception-type>
<location>/invalidSession.jsp</location>
</error-page>

在 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、付费专栏及课程。

余额充值