shiro-redis ============= [![Build Status](https://travis-ci.org/alexxiyang/shiro-redis.svg?branch=master)](https://travis-ci.org/alexxiyang/shiro-redis) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.crazycake/shiro-redis/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.crazycake/shiro-redis) shiro only provide the support of ehcache and concurrentHashMap. Here is an implement of redis cache can be used by shiro. Hope it will help you! # Download You can choose these 2 ways to include shiro-redis into your project * use "git clone https://github.com/alexxiyang/shiro-redis.git" to clone project to your local workspace and build jar file by your self * add maven dependency ```xml org.crazycake shiro-redis 3.2.3 ``` > **Note:**\ > Do not use version < 3.1.0\ > **注意**:\ > 请不要使用3.1.0以下版本 # Before use Here is the first thing you need to know. Shiro-redis needs an id field to identify your authorization object in Redis. So please make sure your principal class has a field which you can get unique id of this object. Please setting this id field name by `cacheManager.principalIdFieldName = ` For example: If you create SimpleAuthenticationInfo like the following: ```java @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)token; UserInfo userInfo = new UserInfo(); userInfo.setUsername(usernamePasswordToken.getUsername()); return new SimpleAuthenticationInfo(userInfo, "123456", getName()); } ``` Then the userInfo object is your principal object. You need to make sure `UserInfo` has an unique field to identify it in Redis. Take userId as an example: ```java public class UserInfo implements Serializable{ private Integer userId private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getUserId() { return this.userId; } } ``` Put userId as the value of `cacheManager.principalIdFieldName`, like this: ```properties cacheManager.principalIdFieldName = userId ``` If you're using Spring, the configuration should be ```xml ``` Then shiro-redis will call `userInfo.getUserId()` to get the id for storing Redis object. # How to configure ? You can configure shiro-redis either in `shiro.ini` or in `spring-*.xml` ## shiro.ini Here is the configuration for shiro.ini. ### Redis Standalone ```properties [main] #==================================== # shiro-redis configuration [start] #==================================== #=================================== # Redis Manager [start] #=================================== # Create redisManager redisManager = org.crazycake.shiro.RedisManager # Redis host. If you don't specify host the default value is 127.0.0.1:6379 redisManager.host = 127.0.0.1:6379 #=================================== # Redis Manager [end] #=================================== #========================================= # Redis session DAO [start] #========================================= # Create redisSessionDAO redisSessionDAO = org.crazycake.shiro.RedisSessionDAO # Use redisManager as cache manager redisSessionDAO.redisManager = $redisManager sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager sessionManager.sessionDAO = $redisSessionDAO securityManager.sessionManager = $sessionManager #========================================= # Redis session DAO [end] #========================================= #========================================== # Redis cache manager [start] #========================================== # Create cacheManager cacheManager = org.crazycake.shiro.RedisCacheManager # Principal id field name. The field which you can get unique id to identify this principal. # For example, if you use UserInfo as Principal class, the id field maybe `id`, `userId`, `email`, etc. # Remember to add getter to this id field. For example, `getId()`, `getUserId()`, `getEmail()`, etc. # Default value is id, that means your principal object must has a method called `getId()` # cacheManager.principalIdFieldName = id # Use redisManager as cache manager cacheManager.redisManager = $redisManager securityManager.cacheManager = $cacheManager #========================================== # Redis cache manager [end] #========================================== #================================= # shiro-redis configuration [end] #================================= ``` For complete configurable options list, check [Configurable Options](#configurable-options). Here is a [tutorial project](https://github.com/alexxiyang/shiro-redis-tutorial) for you to understand how to configure `shiro-redis` in `shiro.ini`. ### Redis Sentinel if you're using Redis Sentinel, please change the redisManager configuration into the following: ```properties #=================================== # Redis Manager [start] #=================================== # Create redisManager redisManager = org.crazycake.shiro.RedisSentinelManager # Sentinel host. If you don't specify host the default value is 127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381 redisManager.host = 127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381 # Sentinel master name redisManager.masterName = mymaster #=================================== # Redis Manager [end] #=================================== ``` For complete configurable options list, check [Configurable Options](#configurable-options). ### Redis Cluster If you're using redis cluster, here is an example of configuration : ```properties #=================================== # Redis Manager [start] #=================================== # Create redisManager redisManager = org.crazycake.shiro.RedisClusterManager # Redis host and port list redisManager.host = 192.168.21.3:7000,192.168.21.3:7001,192.168.21.3:7002,192.168.21.3:7003,192.168.21.3:7004,192.168.21.3:7005 #=================================== # Redis Manager [end] #=================================== ``` For complete configurable options list, check [Configurable Options](#configurable-options). ## Spring ### Redis Standalone spring.xml: ```xml ``` For complete configurable options list, check [Configurable Options](#configurable-options). Here is a [tutorial project](https://github.com/alexxiyang/shiro-redis-spring-tutorial) for you to understand how to configure `shiro-redis` in spring configuration file. ### Redis Sentinel If you use redis sentinel, here is an example of configuration : ```xml ``` For complete configurable options list, check [Configurable Options](#configurable-options). ### Redis Cluster If you use redis cluster, here is an example of configuration : ```xml ``` For complete configurable options list, check [Configurable Options](#configurable-options). ## Serializer Since redis only accept `byte[]`, there comes to a serializer problem. Shiro-redis is using StringSerializer as key serializer and ObjectSerializer as value serializer. You can use your own custom serializer, as long as this custom serializer implemens `org.crazycake.shiro.serializer.RedisSerializer` For example, let's change the charset of keySerializer. ```properties # If you want change charset of keySerializer or use your own custom serializer, you need to define serializer first # # cacheManagerKeySerializer = org.crazycake.shiro.serializer.StringSerializer # Supported encodings refer to https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html # UTF-8, UTF-16, UTF-32, ISO-8859-1, GBK, Big5, etc # # cacheManagerKeySerializer.charset = UTF-8 # cacheManager.keySerializer = $cacheManagerKeySerializer ``` These 4 Serializers are replaceable: - cacheManager.keySerializer - cacheManager.valueSerializer - redisSessionDAO.keySerializer - redisSessionDAO.valueSerializer ## Configurable Options ### RedisManager | Title | Default | Description | | :------------------| :------------------- | :---------------------------| | host | `127.0.0.1:6379` | Redis host. If you don't specify host the default value is `127.0.0.1:6379`. If you run redis in sentinel mode or cluster mode, separate host names with comma, like `127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381` | | masterName | `mymaster` | **Only used for sentinel mode**
The master node of Redis sentinel mode | | timeout | `2000` | Redis connect timeout. Timeout for jedis try to connect to redis server(In milliseconds) | | soTimeout | `2000` | **Only used for sentinel mode or cluster mode**
The timeout for jedis try to read data from redis server | | maxAttempts | `3` | **Only used for cluster mode**
Max attempts to connect to server | | password | | Redis password | | database | `0` | Redis database. Default value is 0 | | jedisPoolConfig | `new redis.clients.jedis.JedisPoolConfig()` | JedisPoolConfig. You can create your own JedisPoolConfig instance and set attributes as you wish
Most of time, you don't need to set jedisPoolConfig
Here is an example.
`jedisPoolConfig = redis.clients.jedis.JedisPoolConfig`
`jedisPoolConfig.testWhileIdle = false`
`redisManager.jedisPoolConfig = jedisPoolConfig` | | count | `100` | Scan count. Shiro-redis use Scan to get keys, so you can define the number of elements returned at every iteration. | | jedisPool | `null` | **Only used for sentinel mode or single mode**
You can create your own JedisPool instance and set attributes as you wish | ### RedisSessionDAO | Title | Default | Description | | :------------------| :------------------- | :---------------------------| | redisManager | | RedisManager which you just configured above (Required) | | expire | `-2` | Redis cache key/value expire time. The expire time is in second.
Special values:
`-1`: no expire
`-2`: the same timeout with session
Default value: `-2`
**Note**: Make sure expire time is longer than session timeout. | | keyPrefix | `shiro:session:` | Custom your redis key prefix for session management
**Note**: Remember to add colon at the end of prefix. | | sessionInMemoryTimeout | `1000` | When we do signin, `doReadSession(sessionId)` will be called by shiro about 10 times. So shiro-redis save Session in ThreadLocal to remit this problem. sessionInMemoryTimeout is expiration of Session in ThreadLocal.
Most of time, you don't need to change it. | | sessionInMemoryEnabled | `true` | Whether or not enable temporary save session in ThreadLocal | | keySerializer | `org.crazycake.shiro.serializer.StringSerializer` | The key serializer of cache manager
You can change the implement of key serializer or the encoding of StringSerializer.
Supported encodings refer to [Supported Encodings](https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html). Such as `UTF-8`, `UTF-16`, `UTF-32`, `ISO-8859-1`, `GBK`, `Big5`, etc
For more detail, check [Serializer](#serializer) | | valueSerializer | `org.crazycake.shiro.serializer.ObjectSerializer` | The value serializer of cache manager
You can change the implement of value serializer
For more detail, check [Serializer](#serializer) | ### CacheManager | Title | Default | Description | | :--------------------| :------------------- | :---------------------------| | redisManager | | RedisManager which you just configured above (Required) | | principalIdFieldName | `id` | Principal id field name. The field which you can get unique id to identify this principal.
For example, if you use UserInfo as Principal class, the id field maybe `id`, `userId`, `email`, etc.
Remember to add getter to this id field. For example, `getId()`, `getUserId(`), `getEmail()`, etc.
Default value is `id`, that means your principal object must has a method called `getId()` | | expire | `1800` | Redis cache key/value expire time.
The expire time is in second. | | keyPrefix | `shiro:cache:` | Custom your redis key prefix for cache management
**Note**: Remember to add colon at the end of prefix. | | keySerializer | `org.crazycake.shiro.serializer.StringSerializer` | The key serializer of cache manager
You can change the implement of key serializer or the encoding of StringSerializer.
Supported encodings refer to [Supported Encodings](https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html). Such as `UTF-8`, `UTF-16`, `UTF-32`, `ISO-8859-1`, `GBK`, `Big5`, etc
For more detail, check [Serializer](#serializer) | | valueSerializer | `org.crazycake.shiro.serializer.ObjectSerializer` | The value serializer of cache manager
You can change the implement of value serializer
For more detail, check [Serializer](#serializer) | # Spring boot starter Shiro-redis’s Spring-Boot integration is the easiest way to integrate Shiro-redis into a Spring-base application. > Note: `shiro-redis-spring-boot-starter` version `3.2.1` is based on `shiro-spring-boot-web-starter` version `1.4.0-RC2` First include the Shiro-redis Spring boot starter dependency in you application classpath ```xml org.crazycake shiro-redis-spring-boot-starter 3.2.1 ``` The next step depends on whether you've created your own `SessionManager` or `SessionsSecurityManager`. Because `shiro-redis-spring-boot-starter` will create `RedisSessionDAO` and `RedisCacheManager` for you. Then inject them into `SessionManager` and `SessionsSecurityManager` automatically. But if you've created your own `SessionManager` or `SessionsSecurityManager` as below: ```java @Bean public SessionsSecurityManager securityManager(List realms) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realms); // other stuff return securityManager; } ``` You will have to inject them by yourself. for more deail, see below ## If you haven't created your own `SessionManager` or `SessionsSecurityManager` You are all set. Enjoy it! ## If you have created your own `SessionManager` or `SessionsSecurityManager` Inject `redisSessionDAO` and `redisCacheManager` which created by `shiro-redis-spring-boot-starter` already ```java @Autowired RedisSessionDAO redisSessionDAO; @Autowired RedisCacheManager redisCacheManager; ``` Inject them into `SessionManager` and `SessionsSecurityManager` ```java @Bean public SessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); // inject redisSessionDAO sessionManager.setSessionDAO(redisSessionDAO); return sessionManager; } @Bean public SessionsSecurityManager securityManager(List realms, SessionManager sessionManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realms); //inject sessionManager securityManager.setSessionManager(sessionManager); // inject redisCacheManager securityManager.setCacheManager(redisCacheManager); return securityManager; } ``` For full example, see [shiro-redis-spring-boot-tutorial](https://github.com/alexxiyang/shiro-redis-spring-boot-tutorial) ### Configuration Properties | Title | Default | Description | | :--------------------------------------------------| :------------------- | :---------------------------| | shiro-redis.enabled | `true` | Enables shiro-redis’s Spring module | | shiro-redis.redis-manager.deploy-mode | `standalone` | Redis deploy mode. Options: `standalone`, `sentinel`, 'cluster' | | shiro-redis.redis-manager.host | `127.0.0.1:6379` | Redis host. If you don't specify host the default value is `127.0.0.1:6379`. If you run redis in sentinel mode or cluster mode, separate host names with comma, like `127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381` | | shiro-redis.redis-manager.master-name | `mymaster` | **Only used for sentinel mode**
The master node of Redis sentinel mode | | shiro-redis.redis-manager.timeout | `2000` | Redis connect timeout. Timeout for jedis try to connect to redis server(In milliseconds) | | shiro-redis.redis-manager.so-timeout | `2000` | **Only used for sentinel mode or cluster mode**
The timeout for jedis try to read data from redis server | | shiro-redis.redis-manager.max-attempts | `3` | **Only used for cluster mode**
Max attempts to connect to server | | shiro-redis.redis-manager.password | | Redis password | | shiro-redis.redis-manager.database | `0` | Redis database. Default value is 0 | | shiro-redis.redis-manager.count | `100` | Scan count. Shiro-redis use Scan to get keys, so you can define the number of elements returned at every iteration. | | shiro-redis.session-dao.expire | `-2` | Redis cache key/value expire time. The expire time is in second.
Special values:
`-1`: no expire
`-2`: the same timeout with session
Default value: `-2`
**Note**: Make sure expire time is longer than session timeout. | | shiro-redis.session-dao.key-prefix | `shiro:session:` | Custom your redis key prefix for session management
**Note**: Remember to add colon at the end of prefix. | | shiro-redis.session-dao.session-in-memory-timeout | `1000` | When we do signin, `doReadSession(sessionId)` will be called by shiro about 10 times. So shiro-redis save Session in ThreadLocal to remit this problem. sessionInMemoryTimeout is expiration of Session in ThreadLocal.
Most of time, you don't need to change it. | | shiro-redis.session-dao.session-in-memory-enabled | `true` | Whether or not enable temporary save session in ThreadLocal | | shiro-redis.cache-manager.principal-id-field-name | `id` | Principal id field name. The field which you can get unique id to identify this principal.
For example, if you use UserInfo as Principal class, the id field maybe `id`, `userId`, `email`, etc.
Remember to add getter to this id field. For example, `getId()`, `getUserId(`), `getEmail()`, etc.
Default value is `id`, that means your principal object must has a method called `getId()` | | shiro-redis.cache-manager.expire | `1800` | Redis cache key/value expire time.
The expire time is in second. | | shiro-redis.cache-manager.key-prefix | `shiro:cache:` | Custom your redis key prefix for cache management
**Note**: Remember to add colon at the end of prefix. | ## Working with `spring-boot-devtools` If you are using `shiro-redis` with `spring-boot-devtools`. Please add this line to `resources/META-INF/spring-devtools.properties` (Create it if there is no this file): ```ini restart.include.shiro-redis=/shiro-[\\w-\\.]+jar ``` # If you found any bugs Please create the issue 可以用中文