152 Star 394 Fork 126

BYStudio / shiro-redis

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 15.57 KB
一键复制 编辑 原始数据 按行查看 历史
bosco_liao 提交于 2021-05-26 13:16 . update README.md.

avatar Shiro-Redis

Shiro集成Redis的适配器,为解决shiro-ehcache不利于集群而打造的集中式缓存方案。

License Maven Central

Maven坐标

<dependency>
    <groupId>org.iherus.shiro</groupId>
    <artifactId>shiro-redis</artifactId>
    <version>2.5.0</version>
</dependency>

SpringBoot:

<dependency>
    <groupId>org.iherus.shiro</groupId>
    <artifactId>shiro-redis-spring-boot-web-starter</artifactId>
    <version>2.5.0</version>
</dependency>

更新日志

v2.5.0:
Change Log
1)解决Issues:#I1YUFN#I2BSCN#I2B7LC#I22K17#I26UHZ
2)支持session永不失效,#I2BCKL

v2.4.0:【存在bug,请忽略此版本】
常规bug fix 版本

v2.3.0:
Change Log
1)解决RedisSessionDAO#uncache方法抛出StackOverflowError。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

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集成的方式

    <!-- SHIRO安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="userRealm" />
        <property name="cacheManager" ref="cacheManager" />
        <property name="rememberMeManager" ref="rememberMeManager" />
        <property name="sessionManager" ref="sessionManager" />
    </bean>

    <!-- 用户域 -->
    <bean id="userRealm" class="org.iherus.shiro.tester.CustomRealm" />

    <!-- 会话管理器-->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <property name="sessionDAO" ref="sessionDAO" />
        <property name="globalSessionTimeout" value="${shiro.globalSessionTimeout}" />
        <property name="deleteInvalidSessions" value="${shiro.deleteInvalidSessions}" />
        <property name="sessionValidationInterval" value="${shiro.sessionValidationInterval}" />
    </bean>

    <!-- sessionDAO-->
    <bean id="sessionDAO" class=" org.iherus.shiro.cache.redis.RedisSessionDAO">
	<property name="cacheManager" ref="cacheManager" />
    </bean>

    <!-- 记住登录管理器 -->
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <property name="cookie" ref="rememberMeCookie" />
    </bean>

    <!-- Cookie对象 -->
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <property name="name" value="${shiro.cookieName}" />
        <property name="maxAge" value="${shiro.cookieMaxAge}" />
    </bean>

    <!-- 缓存管理器 -->
    <bean id="cacheManager" class="org.iherus.shiro.cache.redis.RedisCacheManager">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="database" value="2" />
        <property name="expirationMillis" value="90000" />
        <property name="keyPrefix" value="shiro:cache:" />
        <property name="scanBatchSize" value="3000" />
        <property name="deleteBatchSize" value="5000" />
        <property name="fetchBatchSize" value="50" />
    </bean>

    <!-- Redis连接工厂 -->
    <bean id="connectionFactory" class="org.iherus.shiro.cache.redis.connection.jedis.JedisConnectionFactory">
	<property name="clientName" value="SRC" />
	<property name="connectTimeoutMillis" value="3000" />
	<property name="soTimeoutMillis" value="2000" />
	<property name="poolConfig" ref="poolConfig" />
	<property name="configuration" ref="standaloneConfiguration" />
	<!-- <property name="configuration" ref="sentinelConfiguration" /> -->
	<!-- <property name="configuration" ref="clusterConfiguration" />  -->
    </bean>

    <!-- Redis单机配置 -->
    <bean id="standaloneConfiguration" class="org.iherus.shiro.cache.redis.config.RedisStandaloneConfiguration">
	<property name="host" value="127.0.0.1" />
	<property name="port" value="6379" />
	<property name="database" value="0" />
	<!-- <property name="password" value="" /> -->
    </bean>

    <!-- Redis哨兵配置 -->
    <bean id="sentinelConfiguration" class="org.iherus.shiro.cache.redis.config.RedisSentinelConfiguration">
	<property name="masterName" value="mymaster" />
	<property name="sentinelsFromText" value="127.0.0.1:56379,127.0.0.1:56479,127.0.0.1:56579" />
	<!-- <property name="password" value="" /> -->
    </bean>

    <!-- Redis集群配置 -->
    <bean id="clusterConfiguration" class="org.iherus.shiro.cache.redis.config.RedisClusterConfiguration">
	<property name="clusterNodesFromText" value="127.0.0.1:16379,127.0.0.1:16380,127.0.0.1:16381..." />
	<property name="maxAttempts" value="5" />
	<!-- <property name="password" value="" /> -->
    </bean>

    <!-- 配置缓存连接池 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="minIdle" value="${redis.minIdle}" />
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
        <property name="maxTotal" value="${redis.maxTotal}" />
    </bean>

3、Spring Boot集成的方式

3-1)引入Spring Boot Starter依赖项:

        <dependency>
            <groupId>org.iherus.shiro</groupId>
            <artifactId>shiro-redis-spring-boot-web-starter</artifactId>
            <version>{latestVersion}</version>
        </dependency>

$\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<Realm> 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

Java
1
https://gitee.com/BYSRepo/shiro-redis.git
git@gitee.com:BYSRepo/shiro-redis.git
BYSRepo
shiro-redis
shiro-redis
master

搜索帮助