我们知道,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.beans.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<Session> 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.setDeleteInvalidSessions(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=================
==============doReadSession=================
==============doReadSession=================
权限配置-->MyShiroRealm.doGetAuthorizationInfo()
==============doReadSession=================

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

Spring boot整合redis实现shiro的分布式session共享的更多相关文章

  1. SpringBoot入门系列(七)Spring Boot整合Redis缓存

    前面介绍了Spring Boot 中的整合Mybatis并实现增删改查,.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/ ...

  2. Spring Boot 整合 Redis 和 JavaMailSender 实现邮箱注册功能

    Spring Boot 整合 Redis 和 JavaMailSender 实现邮箱注册功能 开篇 现在的网站基本都有邮件注册功能,毕竟可以通过邮件定期的给用户发送一些 垃圾邮件 精选推荐

  3. (转)spring boot整合redis

    一篇写的更清晰的文章,包括redis序列化:http://makaidong.com/ncjava/330749_5285125.html 1.项目目录结构 2.引入所需jar包 <!-- Sp ...

  4. Spring Boot2 系列教程(二十六)Spring Boot 整合 Redis

    在 Redis 出现之前,我们的缓存框架各种各样,有了 Redis ,缓存方案基本上都统一了,关于 Redis,松哥之前有一个系列教程,尚不了解 Redis 的小伙伴可以参考这个教程: Redis 教 ...

  5. Spring Boot 整合 Redis 实现缓存操作

    摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢!   『 产品没有价值,开发团队再优秀也无济于事 – <启示录> 』   本文提纲 ...

  6. spring boot整合redis,以及设置缓存过期时间

    spring-boot 整合 redis 注:redis服务器要先开启 pom文件: <dependency> <groupId>org.springframework.boo ...

  7. spring boot 2.x 系列 —— spring boot 整合 redis

    文章目录 一.说明 1.1 项目结构 1.2 项目主要依赖 二.整合 Redis 2.1 在application.yml 中配置redis数据源 2.2 封装redis基本操作 2.3 redisT ...

  8. Spring Boot2 系列教程(二十九)Spring Boot 整合 Redis

    经过 Spring Boot 的整合封装与自动化配置,在 Spring Boot 中整合Redis 已经变得非常容易了,开发者只需要引入 Spring Data Redis 依赖,然后简单配下 red ...

  9. Spring Boot 整合Redis 实现缓存

      本文提纲 一.缓存的应用场景 二.更新缓存的策略 三.运行 springboot-mybatis-redis 工程案例 四.springboot-mybatis-redis 工程代码配置详解   ...

随机推荐

  1. 九度OJ #1437 To Fill or Not to Fil

    题目描写叙述: With highways available, driving a car from Hangzhou to any other city is easy. But since th ...

  2. PHPMailer发送邮件乱码

    PHPMailer发送邮件乱码, $mail->CharSet="GB2312";$mail->Encoding = "base64"; 设成这样不 ...

  3. C# -- 推断字符能否转化为整形

    int iNum = 0; string sNumber = "1003"; int iResult = 0; int.TryParse(sNumber, out iResult) ...

  4. 汉澳sinox不受openssl心血漏洞影响并分析修复其漏洞代码

    OpenSSL 心血(HeartBleed)漏洞 是openssl 在 2014-04-07 发布的重大安全漏洞(CVE-2014-0160)这个漏洞使攻击者可以从server内存中读取64 KB的数 ...

  5. csu1116 Kingdoms 最小生成树-枚举状态

    题目链接: csu 1116 题意: 有一幅双向图连接N个城市(标号1~n,1表示首都)  每一个城市有一个价值W. 地震摧毁了全部道路,现给出可修复的m条道路并给出修复每条道路所需的费用 问在总费用 ...

  6. wxpython中鼠标样式的获取与匹配

    在wxpython中定义有多种默认的鼠标样式,譬如:wx.CURSORCROSS wx.CURSORHAND等等, 此处按下不表,可以参考wxpython的samples里面自带的cursor例子 这 ...

  7. Lazy freeing of keys 对数据的额异步 同步操作 Redis 4.0 微信小程序

    https://github.com/antirez/redis/blob/4.0-rc1/00-RELEASENOTES 数据缓存 · 小程序 https://developers.weixin.q ...

  8. CSS3 的10种Loading

    昨晚用CSS3实现了几种常见的Loading效果,虽然很简单,但还是分享一下,顺便也当是做做笔记…… 第1种效果: 代码如下: <div class="loading"> ...

  9. 求a + aa + aaa + aaaa + aaaaa ...的值,例如:1 + 11 + 111,2 + 22 + 222 + 2222 + 22222

    #include <stdio.h> unsigned superposition(unsigned m, unsigned n); int main() { printf("1 ...

  10. spring-jar包详解整理(大合集)

    转:https://blog.csdn.net/weisong530624687/article/details/50888094 spring.jar 是包含有完整发布模块的单个jar 包.但是不包 ...