# shiro-redis **Repository Path**: BYSRepo/shiro-redis ## Basic Information - **Project Name**: shiro-redis - **Description**: 基于Redis的shiro集中式缓存解决方案 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 392 - **Forks**: 126 - **Created**: 2016-04-13 - **Last Updated**: 2025-02-10 ## Categories & Tags **Categories**: cache-modules **Tags**: None ## README ## ![avatar](/logo.png) Shiro-Redis Shiro集成Redis的适配器,为解决shiro-ehcache不利于集群而打造的集中式缓存方案。 [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) [![Maven Central](https://img.shields.io/maven-central/v/org.iherus.shiro/shiro-redis)](https://mvnrepository.com/artifact/org.iherus.shiro/shiro-redis) **Maven坐标** ``` org.iherus.shiro shiro-redis 2.5.0 ``` SpringBoot: ``` org.iherus.shiro shiro-redis-spring-boot-web-starter 2.5.0 ``` ## 更新日志 **v2.5.0:**
**Change Log**
1)解决Issues:[#I1YUFN](https://gitee.com/iherus/shiro-redis/issues/I1YUFN)、[#I2BSCN](https://gitee.com/iherus/shiro-redis/issues/I2BSCN)、 [#I2B7LC](https://gitee.com/iherus/shiro-redis/issues/I2B7LC)、[#I22K17](https://gitee.com/iherus/shiro-redis/issues/I22K17)、[#I26UHZ](https://gitee.com/iherus/shiro-redis/issues/I26UHZ)。
2)支持session永不失效,[#I2BCKL](https://gitee.com/iherus/shiro-redis/issues/I2BCKL) 。
~~**v2.4.0:【存在bug,请忽略此版本】**
~~ 常规bug fix 版本 **v2.3.0:**
**Change Log**
1)解决RedisSessionDAO#uncache方法抛出StackOverflowError。Issues:[#I1TIIG](https://gitee.com/iherus/shiro-redis/issues/I1TIIG)
2)依赖升级,其中Shiro的版本升至1.6.0。
**v2.2.0:** **Change Log**
1)加入scope策略.
**v2.1.0:** **Change Log**
1)修复bug.
2)增强兼容性
3)发布[shiro-redis-spring-boot-web-starter](https://gitee.com/iherus/shiro-redis-spring-boot-web-starter)
**v2.0.0:** **Note**
此版本为重构版本,API不兼容v1.x。 **Change Log**
1)在v1.x仅支持单机模式的基础上,新增了对 哨兵(Sentinel)、集群(Cluster)模式的支持。
2)支持Lettuce客户端、Redisson客户端
3)兼容Spring-data-redis
4)非集群模式,可设置独立的database
5)支持设置缓存失效时间
6)优化性能
7)新增RedisSessionDAO用于降低请求Redis的频率 ## Shiro-Redis使用说明 **1、基于ini的使用方式** ``` [main] #定义凭证匹配器 credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher #散列算法 credentialsMatcher.hashAlgorithmName=MD5 #散列次数 credentialsMatcher.hashIterations=2 #定义缓存池配置 poolConfig=redis.clients.jedis.JedisPoolConfig poolConfig.minIdle=3 poolConfig.maxIdle=10 poolConfig.maxWaitMillis=1500 poolConfig.maxTotal=100 #定义连接配置 ## Standalone configuration=org.iherus.shiro.cache.redis.config.RedisStandaloneConfiguration configuration.host=127.0.0.1 configuration.port=6379 configuration.database=2 #configuration.password= ## Sentinel #configuration=org.iherus.shiro.cache.redis.config.RedisSentinelConfiguration #configuration.masterName=mymaster #configuration.sentinelsFromText=127.0.0.1:56379,127.0.0.1:56479,127.0.0.1:56579 #configuration.database=2 #configuration.password= ## Cluster #configuration=org.iherus.shiro.cache.redis.config.RedisClusterConfiguration #configuration.clusterNodesFromText=127.0.0.1:16379, 127.0.0.1:16380, 127.0.0.1:16381, 127.0.0.1:16382, 127.0.0.1:16383, 127.0.0.1:16384 #configuration.password= #定义连接工厂 ## Jedis connectionFactory=org.iherus.shiro.cache.redis.connection.jedis.JedisConnectionFactory connectionFactory.poolConfig=$poolConfig connectionFactory.configuration=$configuration #connectionFactory.clientName= #connectionFactory.connectTimeoutMillis= #connectionFactory.soTimeoutMillis= ## Lettuce #connectionFactory=org.iherus.shiro.cache.redis.connection.lettuce.LettuceConnectionFactory #connectionFactory.poolConfig=$poolConfig #connectionFactory.configuration=$configuration #connectionFactory.clientName= #connectionFactory.timeoutMillis= ## Redisson #connectionFactory=org.iherus.shiro.cache.redis.connection.redisson.RedissonConnectionFactory #connectionFactory.configuration=$configuration #connectionFactory.clientName= #connectionFactory.connectTimeoutMillis= #connectionFactory.soTimeoutMillis= #定义缓存管理器 cacheManager=org.iherus.shiro.cache.redis.RedisCacheManager cacheManager.connectionFactory=$connectionFactory cacheManager.expirationMillis=900000 cacheManager.keyPrefix=shiro:test:cache: #cacheManager.scanBatchSize=3000 #cacheManager.deleteBatchSize=5000 #cacheManager.fetchBatchSize=50 #cacheManager.database=5 #将凭证匹配器设置到realm customRealm=org.iherus.shiro.tester.CustomRealm customRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$customRealm securityManager.cacheManager=$cacheManager ``` 详细测试代码请看:src/test/java/org/iherus/shiro /tester/SimpleCacheTest.java **2、Spring集成的方式** ``` ``` **3、Spring Boot集成的方式** 3-1)引入Spring Boot Starter依赖项: ``` org.iherus.shiro shiro-redis-spring-boot-web-starter {latestVersion} ``` $\color{red}{注意:由于客户端工具是可选依赖,所以,请根据需要引入相应依赖,支持jedis、lettuce、redisson和spring-data-redis,}$
$\color{red}{如若使用lettuce,还需要再引入commons-pool2。}$ 3-2)默认情况下,shiro-redis-spring-boot-web-starter会自动创建 RedisCacheManager 和 RedisSessionDAO 实例并注入 WebSecurityManager 和 WebSessionManager中,如果您需要自定义 SecurityManager 和 SessionManager。
示例如下: ``` @Bean public SessionManager sessionManager(SessionDAO sessionDAO) { DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager(); // 注入RedisSessionDAO实例 webSessionManager.setSessionDAO(sessionDAO); .....other..... return webSessionManager; } @Bean public DefaultWebSecurityManager securityManager(SessionManager sessionManager, CacheManager cacheManager, List realms) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 注入SessionManager实例 securityManager.setSessionManager(sessionManager); // 注入cacheManager实例 securityManager.setCacheManager(cacheManager != null ? cacheManager : new MemoryConstrainedCacheManager()); securityManager.setRealms(realms); .....other..... return securityManager; } ``` 3-3)SSL相关配置,提供了接口:JedisSslClientConfigurationCustomizer、LettuceClientConfigurationCustomizer、RedissonSslClientConfigurationCustomizer,可根据需要去实现定制器,并注册Bean。
示例如下: ``` @Bean public JedisSslClientConfigurationCustomizer JedisSslClientConfigurationCustomizer() { return ((builder) -> { ....SSL配置.... }); } ``` 3-4)配置属性 | 属性项 | 缺省 | 描述 | |-----|----|----| |**基本配置**| | shiro.redis.host|localhost|主机名| | shiro.redis.port |6379|端口| | shiro.redis.database |0 | 数据库 | | shiro.redis.password ||密码| | shiro.redis.sentinel.master-name ||哨兵模式中主节点名称| | shiro.redis.sentinel.nodes ||哨兵节点地址串,逗号分隔,eg:127.0.0.1:56379,127.0.0.1:56479,127.0.0.1:56579| | shiro.redis.cluster.max-attempts | 5 | 最大重试次数 | | shiro.redis.cluster.nodes | | 集群节点地址串,逗号分隔,eg: 127.0.0.1:16379,127.0.0.1:16380,127.0.0.1:16381... | |**Jedis**| | shiro.redis.jedis.client-name ||客户端名称| | shiro.redis.jedis.connect-timeout |2000ms|连接超时| | shiro.redis.jedis.so-timeout |2000ms|读取超时| | shiro.redis.jedis.ssl |false|是否启用SSL| | shiro.redis.jedis.pool.min-idle |3|| | shiro.redis.jedis.pool.max-idle |8|| | shiro.redis.jedis.pool.max-total |8|| | shiro.redis.jedis.pool.max-wait-millis |90000|| | shiro.redis.jedis.pool.min-evictable-idle-time-millis |60000|| | shiro.redis.jedis.pool.test-on-borrow |false|| | shiro.redis.jedis.pool.test-while-idle |true|| | shiro.redis.jedis.pool.time-between-eviction-runs-millis |30000|| | shiro.redis.jedis.pool.num-tests-per-eviction-run |-1|| |**Lettuce**| | shiro.redis.lettuce.client-name ||客户端名称| | shiro.redis.lettuce.read-from ||读操作节点偏好| | shiro.redis.lettuce.ssl |false|是否启用SSL| | shiro.redis.lettuce.verify-peer |true|是否启用SSL证书校验| | shiro.redis.lettuce.start-tls |false|是否启用StartTLS| | shiro.redis.lettuce.pool.min-idle |3|| | shiro.redis.lettuce.pool.max-idle |8|| | shiro.redis.lettuce.pool.max-total |8|| | shiro.redis.lettuce.pool.max-wait-millis |90000|| | shiro.redis.lettuce.pool.min-evictable-idle-time-millis |60000|| | shiro.redis.lettuce.pool.test-on-borrow |false|| | shiro.redis.lettuce.pool.test-while-idle |true|| | shiro.redis.lettuce.pool.time-between-eviction-runs-millis |30000|| | shiro.redis.lettuce.pool.num-tests-per-eviction-run |-1|| |**Redisson**| | shiro.redis.redisson.client-name ||客户端名称| | shiro.redis.redisson.connect-timeout |10000ms|连接超时| | shiro.redis.redisson.connection-min-idle-size |8|最少空闲连接数| | shiro.redis.redisson.connection-pool-size |32|连接池大小| | shiro.redis.redisson.so-timeout |3000ms|读取超时| | shiro.redis.redisson.ssl |false|是否启用SSL| |**Shiro缓存配置**| | shiro.redis.cache.batch-options.delete-batch-size | 5000 | 批量删除数量 | | shiro.redis.cache.batch-options.fetch-batch-size | 50 | 批量获取数量 | | shiro.redis.cache.batch-options.scan-batch-size | 3000 | 每批次扫描数量 | | shiro.redis.cache.database | 0 | shiro缓存数据库 | | shiro.redis.cache.expiration | PT15M | shiro缓存失效时长 | | shiro.redis.cache.key-prefix | shiro:cache: | shiro缓存键前缀 | **4、关于缓存key的特别说明**     针对非 byte[] 和 String 类型的缓存key,采用的是生成MD5作为key的策略,这样就要求AuthorizingRealm#doGetAuthenticationInfo返回的[PrincipalCollection principals]必须是一成不变的,这样一来,如果后续需要动态修改principals的属性,则会导致缓存key的变化。
所以,建议重写这两个方法来应对这种变化: 1)AuthorizingRealm #getAuthorizationCacheKey(PrincipalCollection principals)
2)AuthorizingRealm #getAuthenticationCacheKey(PrincipalCollection principals)
eg: ``` /** * 建议重写此方法,提供唯一的缓存Key */ @Override protected Object getAuthorizationCacheKey(PrincipalCollection principals) { return this.getAuthenticationCacheKey(principals); } /** * 建议重写此方法,提供唯一的缓存Key */ @SuppressWarnings("unchecked") @Override protected Object getAuthenticationCacheKey(PrincipalCollection principals) { StringBuilder sb = new StringBuilder(); principals.forEach(principal -> { sb.append(((User) principal).getId()); }); return sb.toString(); } ``` 更多正在补充中。。。。。 :smile: **Features** 欢迎提出更好的意见,帮助完善 shiro-redis **Copyright** Apache License, Version 2.0