shiro+redis实现用户权限集缓存功能
本文开发环境:springboot2+thymeleaf+shiro+redis
通过redis实现对用户权限集的缓存功能。
1,pom.xml引入包
①在使用shiro的情况下集成redis
<dependency>
<groupId>org.crazycakegroupId>
<artifactId>shiro-redisartifactId>
<version>2.4.2.1-RELEASEversion>
dependency>
②springboot集成redis
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-redisartifactId>
<version>1.4.7.RELEASEversion>
dependency>
③ shiro-redis中引入的有jedis3.1.0包,访问控制符是protected,需要引用低版本才能使用2.9.0 public
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>2.9.0version>
dependency>
④注释devTools热部署插件,和redis缓存冲突(可能会发生,发生就注释)
2,redis连接配置
#### redis服务器配置 ####
##redis服务器地址
spring.redis.host = localhost
##端口
spring.redis.port = 6379
# Redis数据库索引(默认为0)
spring.redis.database=0
3,启动redis服务
4,doGetAuthenticationInfo身份认证代码略。
5,ShiroRealm配置doGetAuthorizationInfo授权认证,获取权限集
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SysEmployee employee = (SysEmployee) principals.getPrimaryPrincipal();
Long id = employee.getId();
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// 获取用户角色集
List
Set
simpleAuthorizationInfo.setRoles(roleSet);
// 获取用户权限集
List
Set
simpleAuthorizationInfo.setStringPermissions(permissionSet);
return simpleAuthorizationInfo;
}
6,ShiroConfig
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm());
// 自定义缓存实现 使用redis
securityManager.setCacheManager(cacheManager());
//注入记住我管理器
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
@Bean
public ShiroRealm shiroRealm() {
// 配置 Realm,需自己实现
ShiroRealm shiroRealm = new ShiroRealm();
shiroRealm.setCredentialsMatcher(new MyCredentialsMatcher());
return shiroRealm;
}
/**
* cacheManager 缓存 redis实现
* @return
*/
public RedisCacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
// redisCacheManager.setRedisManager(redisManager());
return redisCacheManager;
}
7,自定义redis缓存管理器RedisCacheManager
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
//自定义shiro缓存管理器
public class RedisCacheManager implements CacheManager {
//参数1:认证或者是授权缓存的统一名称
@Override
public
//System.out.println(cacheName);
return new RedisCache
}
}
8,自定义redis缓存实现 RediCache
import com.mly.oa.hospital.util.SpringContextUtil;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.Collection;
import java.util.Set;
//自定义redisCache缓存实现
public class RedisCache
private String cacheName;
public RedisCache() {
}
public RedisCache(String cacheName) {
this.cacheName = cacheName;
}
@Override
public v get(k k) throws CacheException {
// System.out.println(" key:"+k);
return (v) getRedisTemplate().opsForHash().get(this.cacheName,k.toString());
}
@Override
public v put(k k, v v) throws CacheException {
// System.out.println(" key: "+k);
// System.out.println(" value:"+v);
getRedisTemplate().opsForHash().put(this.cacheName,k.toString(),v);
return null;
}
@Override
public v remove(k k) throws CacheException {
return (v) getRedisTemplate().opsForHash().delete(this.cacheName,k.toString());
}
@Override
public void clear() throws CacheException {
getRedisTemplate().delete(this.cacheName);
}
@Override
public int size() {
return getRedisTemplate().opsForHash().size(this.cacheName).intValue();
}
@Override
public Set
return getRedisTemplate().opsForHash().keys(this.cacheName);
}
@Override
public Collection
return getRedisTemplate().opsForHash().values(this.cacheName);
}
private RedisTemplate getRedisTemplate(){
RedisTemplate redisTemplate = (RedisTemplate) SpringContextUtil.getBean("redisTemplate");
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}
9,创建上下文对象工具类
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @author John Lee
* @date 2021/11/14 22:22
*/
@Component
public class SpringContextUtil implements ApplicationContextAware {
/**
* 上下文对象实例
*/
private static ApplicationContext applicationContext;
@Autowired
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 获取applicationContext
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过name获取 Bean.
* @param name
* @return
*/
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
/**
* 通过class获取Bean.
* @param clazz
* @param
* @return
*/
public static
return getApplicationContext().getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
* @param name
* @param clazz
* @param
* @return
*/
public static
return getApplicationContext().getBean(name, clazz);
}
}
10,自定义key-value序列化方式
添加前后对比:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate
RedisTemplate
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
11,系统退出,调用自定义中remove,进行删除当前用户redis缓存
@Override
public v remove(k k) throws CacheException {
System.out.println("=============remove=============");
return (v) getRedisTemplate().opsForHash().delete(this.cacheName,k.toString());
}
附加redis其他相关配置
① bind 127.0.0.1
bind绑定ip只支持这个ip地址连接的请求,在生产环境中,请求外部redis需要注释该项。
② redis3.2版本后新增 protected-mode配置。设置外部网络连接redis服务:
关闭protected-mode,此时外部网络可以直接访问
开启protected-mode,需要配置bind IP 或者设置访问密码
③ daemonize (守护进程),默认请款下redis不是后台运行的,如需要后台运行,设置值为 yes。
windows系统不支持。
④ pidfile /var/run/redis.pid
当redis在后台运行时,redis默认是把pid文件放在/var/run/redis.pid,可以修改到其他位置。当运行多个redis服务时,需要指定不同的pid文件和端口。
windows不支持
⑤ port 监听端口,默认是6379
⑥ timeout 0
设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接。
⑦ tcp-keepalive 0
指定TCP连接是否为长连接,“侦探”信号有server端维护。默认为0,表示禁用
⑧ loglevel notice
log等级为4级,debug,verbose,notice和warning。生产环境下一半开启notice。
⑨ databases 16
设置数据库的个数,默认16个库,默认使用0号库。
⑩ save 900 1 save 300 10 save 60 10000
保存数据快照的频率,将数据持久化到dump.rdb文件中的频率。
默认设置,意思是:
if(在60 秒之内有10000 个keys 发生变化时){ 进行镜像备份
}else if(在300 秒之内有10 个keys 发生了变化){ 进行镜像备份
}else if(在900 秒之内有1 个keys 发生了变化){ 进行镜像备份}
redis更多详细配置:推荐链接https://blog.csdn.net/neubuffer/article/details/17003909