spring boot整合redis实现shiro的分布式session共享的方法

网友投稿 318 2023-02-22


spring boot整合redis实现shiro的分布式session共享的方法

我们知道,shiro是通过SessionManager来管理Session的,而对于Session的操作则是通过SessionDao来实现的,默认的情况下,shiro实现了两种SessionDao,分别为CachingSessionDAO和MemorySessionDAO,当我们使用EhCache缓存时,则是使用的CachingSessionDAO,不适用缓存的情况下,就会选择基于内存的SessionDao.所以,如果我们想实现基于Redis的分布式Session共享,重点在于重写SessionManager中的SessionDao。我们的重写代码如下:

package com.chhliu.springboot.shiro.cache;

import java.io.Serializable;

import java.util.Collection;

import java.util.concurrent.TimeUnit;

import org.apache.shiro.session.Session;

import org.apache.shiro.session.UnknownSessionException;

import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;

import org.springframework.beanhttp://s.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Service;

@Service

@SuppressWarnings({ "rawtypes", "unchecked" })

public class RedisSessionDao extends AbstractSessionDAO {

// Session超时时间,单位为毫秒

private long expireTime = 120000;

@Autowired

private RedisTemplate redisTemplate;// Redis操作类,对这个使用不熟悉的,可以参考前面的博客

public RedisSessionDao() {

super();

}

public RedisSessionDao(long expireTime, RedisTemplate redisTemplate) {

super();

this.expireTime = expireTime;

this.redisTemplate = redisTemplate;

}

@Override // 更新session

public void update(Session session) throws UnknownSessionException {

System.out.println("===============update================");

if (session == null || session.getId() == null) {

return;

}

session.setTimeout(expireTime);

redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.MILLISECONDS);

}

@Override // 删除session

public void delete(Session session) {

System.out.println("===============delete================");

if (null == session) {

return;

}

redisTemplate.opsForValue().getOperations().delete(session.getId());

}

@Override// 获取活跃的session,可以用来统计在线人数,如果要实现这个功能,可以在将session加入redis时指定一个session前缀,统计的时候则使用keys("session-prefix*")的方式来模糊查找redis中所有的session集合

public Collection getActiveSessions() {

System.out.println("==============getActiveSessions=================");

return redisTemplate.keys("*");

}

@Override// 加入session

protected Serializable doCreate(Session session) {

System.out.println("===============doCreate================");

Serializable sessionId = this.generateSessionId(session);

this.assignSessionId(session, sessionId);

redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.MILLISECONDS);

return sessionId;

}

@Override// 读取session

protected Session doReadSession(Serializable sessionId) {

System.out.println("==============doReadSession=================");

if (sessionId == null) {

return null;

}

return (Session) redisTemplate.opsForValue().get(sessionId);

}

public long getExpireTime() {

return expireTime;

}

public void setExpireTime(long expireTime) {

this.expireTime = expireTime;

}

public RedisTemplate getRedisTemplate() {

return redisTemplate;

}

public void setRedisTemplate(RedisTemplate redisTemplate) {

this.redisTemplate = redisTemplate;

}

}

SessionDao实现完了之后,我们就需要将SessionDao加入SessionManager中了,代码如下:

@Bean

public DefaultWebSessionManager configWebSessionManager(){

DefaultWebSessionManager manager = new DefaultWebSessionManager();

manager.setCacheManager(cacheManager);// 加入缓存管理器

manager.setSessionDAO(sessionDao);// 设置SessionDao

manager.setDeleteInvalidSXzOwGiFPeessions(true);// 删除过期的session

manager.setGlobalSessionTimeout(sessionDao.getExpireTime());// 设置全局session超时时间

manager.setSessionValidationSchedulerEnabled(true);// 是否定时检查session

return manager;

}

最后一步就是将SessionManager配置到SecurityManager中了

@Bean

public SecurityManager securityManager(DefaultWebSessionManager webSessionManager) {

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

// 设置realm.

securityManager.setRealm(myShiroRealm());

// 注入缓存管理器;

securityManager.setCacheManager(cacheManager);// 这个如果执行多次,也是同样的一个对象;

// session管理器

securityManager.setSessionManager(webSessionManager);

//注入记住我管理器;

securityManager.setRememberMeManager(rememberMeManager());

return securityManager;

}

测试结果如下:

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

==============doReadSession================= 

===============update================ 

==============doReadSession================= 

==============doReadSession================= 

===============update================ 

==============doReadSession================= 

==XzOwGiFPe============doReadSession================= 

==============doReadSession================= 

权限配置-->MyShiroRealm.doGetAuthorizationInfo() 

==============doReadSession=================

我们会发现,当一个页面中存在多个资源的时候,会不停的调用doReadSession,update方法来读取和更新session,目前这个问题还没有想到比较好的解决方案。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:微信小程序版翻牌小游戏
下一篇:struts2实现简单文件下载功能
相关文章

 发表评论

暂时没有评论,来抢沙发吧~