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.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集成Shiro并利用MongoDB做Session存储的方法详解
  • 详解springboot中redis的使用和分布式session共享问题
  • Spring Boot高级教程之使用Redis实现session共享
  • spring boot实战教程之shiro session过期时间详解
  • 详解SpringBoot中Session超时原理说明
  • Spring Boot报错:No session repository could be auto-configured, check your configuration的解决方法
  • 详解基于Spring Boot/Spring Session/Redis的分布式Session共享解决方案
  • Spring Boot项目利用Redis实现session管理实例
  • 详解Spring-Boot集成Spring session并存入redis
  • spring boot与redis 实现session共享教程
(0)

相关推荐

  • Spring Boot高级教程之使用Redis实现session共享

    Redis是一个缓存消息中间件及具有丰富特性的键值存储系统.Spring Boot为Jedis客户端库和由Spring Data Redis提供的基于Jedis客户端的抽象提供自动配置.spring-boot-starter-redis'Starter POM'为收集依赖提供一种便利的方式. 引入spring-boot-starter-redis,在pom.xml配置文件中增加配置如下(基于之前章节"Spring Boot 构建框架"中的pom.xml文件): <dependen

  • spring boot与redis 实现session共享教程

    如果大家对spring boot不是很了解,大家可以参考下面两篇文章. Spring Boot 快速入门教程 Spring Boot 快速入门指南 这次带来的是spring boot + redis 实现session共享的教程. 在spring boot的文档中,告诉我们添加@EnableRedisHttpSession来开启spring session支持,配置如下: @Configuration @EnableRedisHttpSession public class RedisSessi

  • spring boot实战教程之shiro session过期时间详解

    前言 众所周知在spring boot内,设置session过期时间只需在application.properties内添加server.session.timeout配置即可.在整合shiro时发现,server.session.timeout设置为7200,但未到2小时就需要重新登录,后来发现是shiro的session已经过期了,shiro的session过期时间并不和server.session.timeout一致,目前是采用filter的方式来进行设置. ShiroSessionFil

  • 详解基于Spring Boot/Spring Session/Redis的分布式Session共享解决方案

    分布式Web网站一般都会碰到集群session共享问题,之前也做过一些Spring3的项目,当时解决这个问题做过两种方案,一是利用nginx,session交给nginx控制,但是这个需要额外工作较多:还有一种是利用一些tomcat上的插件,修改tomcat配置文件,让tomcat自己去把Session放到Redis/Memcached/DB中去.这两种各有优缺,也都能解决问题. 但是现在项目全线Spring Boot,并不自己维护Tomcat,而是由Spring去启动Tomcat.这样就会有一

  • Spring Boot报错:No session repository could be auto-configured, check your configuration的解决方法

    本文主要跟大家分享了关于Spring Boot报错:No session repository could be auto-configured, check your configuration的解决方法,下面话不多说,来一起看看详细的介绍: 一.环境介绍 JDK 1.8  spring-Boot 1.5.1.RELEASE, STS IDE 二. 问题的提出 创建了一个非常简约的Spring Boot Web Application,其中使用了Spring-Session,具体的maven依

  • Spring Boot项目利用Redis实现session管理实例

    在现代网络服务中,session(会话)不得不说是非常重要也是一定要实现的概念,因此在web后台开发中,对session的管理和维护是必须要实现的组件.这篇文章主要是介绍如何在Spring Boot项目中加入redis来实现对session的存储与管理. 1. 利用Spring Initializr来新建一个spring boot项目 2. 在pom.xml中添加redis和session的相关依赖.项目生成的时候虽然也会自动生成父依赖,但是1.5.3版本的spring boot的redis相关

  • Spring Boot集成Shiro并利用MongoDB做Session存储的方法详解

    前言 shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/ 它提供了很方便的权限认证和登录的功能. 而springboot作为一个开源框架,必然提供了和shiro整合的功能! 之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mongodb中,这个比较符合mongodb的设计初衷,而且在分布式项目中mongo

  • 详解springboot中redis的使用和分布式session共享问题

    对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash.轮训.根据权重.随机等.不管对于哪一种负载均衡算法,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因此会出现session不同步或者丢失的问题. 实际上实现Session共享的方案很多,其中一种常用的就是使用Tomcat.Jetty等服务器提供的Session共享功能,将Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis)中. 本文旨在

  • 详解Spring-Boot集成Spring session并存入redis

    spring Session 提供了一套用于管理用户 session 信息的API和实现. Spring Session为企业级Java应用的session管理带来了革新,使得以下的功能更加容易实现: 编写可水平扩展的原生云应用. 将session所保存的状态卸载到特定的外部session存储中,如Redis或Apache Geode中,它们能够以独立于应用服务器的方式提供高质量的集群. 当用户使用WebSocket发送请求的时候,能够保持HttpSession处于活跃状态. 在非Web请求的处

  • 详解SpringBoot中Session超时原理说明

    一:前言: 最近支付后台登录一段时间后如果没有任何操作,总是需要重新登录才可以继续访问页面,出现这个问题的原因就是session超时,debug代码后发现session的超时时间是1800s.也就是说当1800秒内没有任何操作,session就会出现超时现象.那这个超时时间是如何设置的呢?然后该如何重新设置此超时时间呢?系统又如何判断session超时的呢?接下来就一一进行解答. 二:系统session超时时间如何默认的? 说明:获取session超时时间的方法为"request.getSess

随机推荐