SpringBoot:Shiro 整合 Redis

甜言蜜语
• 阅读 123

前言

前段时间做了一个图床的小项目,安全框架使用的是Shiro。为了使用户7x24小时访问,决定把项目由单机升级为集群部署架构。但是安全框架shiro只有单机存储的SessionDao,尽管Shrio有基于Ehcache-rmi的组播/广播实现,然而集群的分布往往是跨网段的,甚至是跨地域的,所以寻求新的方案。
架构

方案

使用 redis 集中存储,实现分布式集群共享用户信息,这里我们采用第三方开源插件crazycake来实现,pom.xml 引入:
[XML] 纯文本查看 复制代码
?
<dependency>    /align<groupId>org.springframework.boot</groupId>  /align  <artifactId>spring-boot-starter-data-redis</artifactId>/align</dependency>/align<dependency>   /align <groupId>org.crazycake</groupId>  /align  <artifactId>shiro-redis</artifactId> /align   <version>3.2.3</version>/align</dependecy>
配置 application.properties:
[PowerShell] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
8
9

Redis# 数据库索引(默认为0)redis.database=0

服务器地址 变更为自己的

redis.host=127.0.0.1

服务器连接端口

redis.port=6379

服务器连接密码,如果不设置密码注释掉即可

redis.password=

连接超时时间(毫秒)

redis.timeout=30000
本来crazycake插件已经实现了RedisManager,但是参数不可配,这里我们需要自己重写一下:
[Java] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
public class RedisManager extends WorkAloneRedisManager implements IRedisManager {   
private RedisProperties redis;  
 private JedisPool jedisPool;  
 public RedisManager(RedisProperties redis) {      
 this.redis = redis;    }   
private void init() {      
 synchronized(this) {         
  if (this.jedisPool == null) {               
this.jedisPool = new JedisPool(this.getJedisPoolConfig(), redis.getHost(), redis.getPort(),                       
redis.getTimeout(), redis.getPassword(), redis.getDatabase());           
}       
}   
}   
@Override  
 protected Jedis getJedis() {       
if (this.jedisPool == null) {          
 this.init();       
}       
return this.jedisPool.getResource();   
}}
参数配置 RedisProperties:
[Java] 纯文本查看 复制代码
?
@Data
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {   
private String host;   
private int port;   
private int timeout;   
private String password;   
private int database;}
配置 ShiroConfig:
[Java] 纯文本查看 复制代码
?
/* Shiro权限配置 一定要配置 @Configuration 和 @EnableConfigurationProperties 注解 /
@Configuration
@EnableConfigurationProperties({RedisProperties.class})
public class ShiroConfig {   
private RedisProperties redis;   
public ShiroConfig(RedisProperties redis) {       
this.redis = redis;   
}   
@Bean  
 public UserRealm userRealm() {       
return new UserRealm();   
}   
@Bean   
public ShiroFilterFactoryBean shiroFilterFactoryBean (SecurityManager securityManager) {
       ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/index.html");
       shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        // 拦截器
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
       /**
         * 静态文件
         */
       filterChainDefinitionMap.put("/file/**","anon");
        /**
         * 登录注册
         */
       filterChainDefinitionMap.put("/register.shtml","anon");
       filterChainDefinitionMap.put("/login.shtml","anon");
        /**
        * 管理后台
        */
       filterChainDefinitionMap.put("/sys/**", "roles[admin]");
       filterChainDefinitionMap.put("/**", "authc");
       shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
       return shiroFilterFactoryBean;
   }
    @Bean
    public SessionsSecurityManager securityManager() {
       DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm());
       securityManager.setCacheManager(cacheManager());
        securityManager.setSessionManager(sessionManager());
       return securityManager;
   }
   @Bean
    public DefaultWebSessionManager sessionManager() {
       DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
       sessionManager.setSessionIdUrlRewritingEnabled(false);
        sessionManager.setSessionDAO(redisSessionDAO());
       return sessionManager;
   }
    @Bean
   public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }
   /**
     * cacheManager 缓存 redis实现
     * @return
     */
    public RedisCacheManager cacheManager() {
       RedisCacheManager redisCacheManager = new RedisCacheManager();
       redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
   }
    /**
    * 配置shiro redisManager
     * @return
     */
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager(redis);
       return redisManager;
   }
    /**
    * RedisSessionDAO shiro sessionDao层的实现
    * 原理就是重写 AbstractSessionDAO
     * 有兴趣的小伙伴自行阅读源码
     */
   @Bean
    public RedisSessionDAO redisSessionDAO() {
       RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
       redisSessionDAO.setRedisManager(redisManager());
       return redisSessionDAO;
   }}
小结

是不是很爽,以后重启应用再也不用担心用户投诉了?

点赞
收藏
评论区
推荐文章
Stella981 Stella981
3年前
Shiro踩坑记(一):关于shiro
一)问题描述:我在一个Spring的项目中使用shiro搭建权限控制框架。主要通过shirospringbootwebstarter包快速集成Shiro。但是项目无法启动,报没有authorizer的bean的错误:Nobeannamed'authorizer'available
Stella981 Stella981
3年前
Spring+spring mvc+redis+mybatis+PageHelper
iBase4J是基于java的开源框架搭建分布式系统架构,使用到的开源框架有:SpringMVC,Mybatis,Redis数据和session缓存,分布式,单点登录,shiro权限管理,dubbo扩展,Rest等等;http://git.oschina.net/iBase4J/iBase4J(http://git.oschina.net/iBase4J
Stella981 Stella981
3年前
Oauth与Shiro整合的开源项目
Oauth与Shiro整合的开源项目博客分类:java架构ApacheOLTU是JAVA的OAUTH参考实现;Shiro是轻量级的权限管理框架;二者整合,提供一个轻量的OAUTH2应用框架,并根据不同的应用场景提供不同的实现(WEB,移动端);提供基于OAUTH的5类grant\_type的实现;相比之前已经实现的 spri
Stella981 Stella981
3年前
Spring Security使用详解1(基本用法 )
一般项目都会有严格的认证和授权操作,而在Java开发领域常见的安全框架有Shiro和SpringSecurity。本文首先介绍下后者。一、基本用法1、什么是SpringSecurity?SpringSecurity是一个相对复杂的安全管理框架,功能比Shiro更加强大,权限控制细粒度更高,对O
Stella981 Stella981
3年前
SpringBoot + Redis + Shiro 实现权限管理(转)
概述  本文基于网上整理,为了实现将Shiro框架的session存储到redis里面,进而实现基于Niginx负载均衡,多站点部署;maven下shiro依赖<!shiro<dependency<groupIdorg.apache.shiro</groupId
Stella981 Stella981
3年前
SpringBoot2.0高级案例(01): 整合 Shiro 框架,实现用户权限管理
一、Shiro简介1、基础概念ApacheShiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。作为一款安全框架Shiro的设计相当巧妙。Shiro的应用不依赖任何容器,它不仅可以在JavaEE下使用,还可以应用在JavaSE环境中。2、核心角色1)Subject:
Easter79 Easter79
3年前
SpringBoot整合Shiro 集成Redis缓存(六)
简介:由于考虑到项目后期分布式部署,所以缓存由ehcache改为redis,而redis既有单机版部署,也有分布式部署,所以二者需要兼容。1\.maven依赖<dependency<groupIdorg.crazycake</groupId<artifactIdshiroredis</artif
Easter79 Easter79
3年前
SpringBoot2.0高级案例(01): 整合 Shiro 框架,实现用户权限管理
一、Shiro简介1、基础概念ApacheShiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。作为一款安全框架Shiro的设计相当巧妙。Shiro的应用不依赖任何容器,它不仅可以在JavaEE下使用,还可以应用在JavaSE环境中。2、核心角色1)Subject:
Stella981 Stella981
3年前
Spring Shiro 使用默认的Session会话管理
项目中用到了shirosession会话管理机制,今天来总结一下,以下都是在springboot框架实现。shiro的session管理机制很完善,也是独立于j2ee容器且不依赖的,所以我们完全可以使用shiro提供给我们的session会话管理来实现我们的业务逻辑,默认提供的sessionDAO是memorySessionDAO,这里也主要讲它的配
Stella981 Stella981
3年前
Shiro 放行Swagger
一、前言在使用SpringBootShiroMybatisSwagger开发后台权限管理系统的时候,由于SpringBoot采用了Shiro框架,同时API接口文档使用的Swagger,遇到一个问题,在SpringBoot集成Shiro后,访问Swagger接口需要登陆才可以,由于在项目成型之前需要做接口测试,所以这里记录下如何在Shi
Stella981 Stella981
3年前
Shiro 核心功能案例讲解 基于SpringBoot 有源码
Shiro核心功能案例讲解基于SpringBoot有源码从实战中学习Shiro的用法。本章使用SpringBoot快速搭建项目。整合SiteMesh框架布局页面。整合Shiro框架实现用身份认证,授权,数据加密功能。通过本章内容,你将学会用户权限的分配规则,SpringBoot整合Sh