在SpringBoot中Shiro缓存使用Redis、Ehcache实现的两种方式实例

SpringBoot 中配置redis作为session 缓存器。 让shiro引用

  • 本文是建立在你是使用这shiro基础之上的补充内容

第一种:Redis缓存,将数据存储到redis 并且开启session存入redis中。

引入pom

    <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>

配置redisConfig

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
} @Bean
//在这里配置缓存reids配置
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
System.out.println("《========【开启redis】 ======== 》 ");
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
} @Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(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);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
} }

配置自定义缓存管理器,引入redis缓存管理器

  • 定义自己的CacheManager
/**
* <p> 自定义cacheManage 扩张shiro里面的缓存 使用reids作缓存 </p>
* <description>
* 引入自己定义的CacheManager
* 关于CacheManager的配置文件在spring-redis-cache.xml中
* </description>
*/
@Component
public class ShiroSpringCacheManager implements CacheManager ,Destroyable{
/**
* 将之上的RedisCacheManager的Bean拿出来 注入于此
*/
@Autowired
private org.springframework.cache.CacheManager cacheManager; public org.springframework.cache.CacheManager getCacheManager() {
return cacheManager;
} public void setCacheManager(org.springframework.cache.CacheManager cacheManager) {
this.cacheManager = cacheManager;
} @Override
public void destroy() throws Exception {
cacheManager = null;
} @Override
public <K, V> Cache<K, V> getCache(String name) {
if (name == null ){
return null;
}
// 新建一个ShiroSpringCache 将Bean放入并实例化
return new ShiroSpringCache<K,V>(name,getCacheManager());
} }
  • 定义自己实现的Shiro的Cache,实现了Shiro包里的Cache
/**
* <p> 自定义缓存 将数据存入到redis中 </p>
*/
@SuppressWarnings("unchecked")
public class ShiroSpringCache<K,V> implements org.apache.shiro.cache.Cache<K, V>{
private static final Logger log = LoggerFactory.getLogger(ShiroSpringCache.class);
private CacheManager cacheManager;
private Cache cache; public ShiroSpringCache(String name, CacheManager cacheManager) {
if(name==null || cacheManager==null){
throw new IllegalArgumentException("cacheManager or CacheName cannot be null.");
}
this.cacheManager = cacheManager;
//这里首先是从父类中获取这个cache,如果没有会创建一个redisCache,初始化这个redisCache的时候
//会设置它的过期时间如果没有配置过这个缓存的,那么默认的缓存时间是为0的,如果配置了,就会把配置的时间赋予给这个RedisCache
//如果从缓存的过期时间为0,就表示这个RedisCache不存在了,这个redisCache实现了spring中的cache
this.cache= cacheManager.getCache(name);
}
@Override
public V get(K key) throws CacheException {
log.info("从缓存中获取key为{}的缓存信息",key);
if(key == null){
return null;
}
ValueWrapper valueWrapper = cache.get(key);
if(valueWrapper==null){
return null;
}
return (V) valueWrapper.get();
} @Override
public V put(K key, V value) throws CacheException {
log.info("创建新的缓存,信息为:{}={}",key,value);
cache.put(key, value);
return get(key);
} @Override
public V remove(K key) throws CacheException {
log.info("干掉key为{}的缓存",key);
V v = get(key);
cache.evict(key);//干掉这个名字为key的缓存
return v;
} @Override
public void clear() throws CacheException {
log.info("清空所有的缓存");
cache.clear();
} @Override
public int size() {
return cacheManager.getCacheNames().size();
} /**
* 获取缓存中所的key值
*/
@Override
public Set<K> keys() {
return (Set<K>) cacheManager.getCacheNames();
} /**
* 获取缓存中所有的values值
*/
@Override
public Collection<V> values() {
return (Collection<V>) cache.get(cacheManager.getCacheNames()).get();
} @Override
public String toString() {
return "ShiroSpringCache [cache=" + cache + "]";
}
}
  • 到此为止,使用redis做缓存,和spring的集成就完成了。

  • 可以使用以下注解将缓存放入redis

 @Cacheable(value = Cache.CONSTANT, key = "'" + CacheKey.DICT_NAME + "'+#name+'_'+#val")

配置spring session管理器

    @Bean
@ConditionalOnProperty(prefix = "xpro", name = "spring-session-open", havingValue = "true")
public ServletContainerSessionManager servletContainerSessionManager() {
return new ServletContainerSessionManager();
}
  • 新建类 spring session设置session过期时间
/**
* spring session配置
*
* @author xingri
* @date 2017-07-13 21:05
*/
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 900) //session过期时间 如果部署多机环境,需要打开注释
@ConditionalOnProperty(prefix = "xpro", name = "spring-session-open", havingValue = "true")
public class SpringSessionConfig { }

第一种:Ehcache做缓存,可以将数据存储到磁盘中,也可以存到内存中

  • 新建ehcache.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" dynamicConfig="false">
<diskStore path="java.io.tmpdir"/>
<!--授权信息缓存-->
<cache name="authorizationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
overflowToDisk="false"
statistics="true">
</cache>
<!--身份信息缓存-->
<cache name="authenticationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
overflowToDisk="false"
statistics="true">
</cache>
<!--session缓存-->
<cache name="activeSessionCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
overflowToDisk="false"
statistics="true">
</cache> <!-- 缓存半小时 -->
<cache name="halfHour"
maxElementsInMemory="10000"
maxElementsOnDisk="100000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
overflowToDisk="false"
diskPersistent="false" /> <!-- 缓存一小时 -->
<cache name="hour"
maxElementsInMemory="10000"
maxElementsOnDisk="100000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="false"
diskPersistent="false" /> <!-- 缓存一天 -->
<cache name="oneDay"
maxElementsInMemory="10000"
maxElementsOnDisk="100000"
eternal="false"
timeToIdleSeconds="86400"
timeToLiveSeconds="86400"
overflowToDisk="false"
diskPersistent="false" /> <!--
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
<defaultCache name="defaultCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="600"
timeToLiveSeconds="600"
overflowToDisk="false"
maxElementsOnDisk="100000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/> </ehcache>

配置自定义缓存管理器,引入ehcache缓存管理器


/**
* ehcache配置
*
*/
@Configuration
@EnableCaching
public class EhCacheConfig { /**
* EhCache的配置
*/
@Bean
public EhCacheCacheManager cacheManager(CacheManager cacheManager) {
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
ManagementService.registerMBeans(cacheManager, mBeanServer, true, true, true, true);
return new EhCacheCacheManager(cacheManager);
} /**
* EhCache的配置
*/
@Bean
public EhCacheManagerFactoryBean ehcache() {
System.out.println("《========【开启ehcache】 ======== 》 ");
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
return ehCacheManagerFactoryBean;
} @Bean
public org.apache.shiro.cache.CacheManager getCacheShiroManager(EhCacheManagerFactoryBean ehcache) {
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManager(ehcache.getObject());
return ehCacheManager;
}
}

最后 最重要的是引入shriro 中


/**
* shiro权限管理的配置
*
*/
@Configuration
public class ShiroConfig { /**
* 安全管理器
*/
@Bean
public DefaultWebSecurityManager securityManager(CookieRememberMeManager rememberMeManager, CacheManager cacheShiroManager, SessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setAuthenticator(modularRealmAuthenticator()); List<Realm> realms=new ArrayList<>();
securityManager.setRealms(realms); securityManager.setCacheManager(cacheShiroManager); securityManager.setRememberMeManager(rememberMeManager);
securityManager.setSessionManager(sessionManager);
return securityManager;
} /**
* spring session管理器(多机环境)
*/
@Bean
public ServletContainerSessionManager servletContainerSessionManager() {
return new ServletContainerSessionManager();
} /**
* session管理器(单机环境) 使用cookie存储缓存。。如果多级请注释
*/
@Bean
public DefaultWebSessionManager defaultWebSessionManager(CacheManager cacheShiroManager, XProProperties xProProperties) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setCacheManager(cacheShiroManager);
sessionManager.setSessionValidationInterval(xProProperties.getSessionValidationInterval() * 1000);
sessionManager.setGlobalSessionTimeout(xProProperties.getSessionInvalidateTime() * 1000);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionValidationSchedulerEnabled(true);
Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
cookie.setName("shiroCookie");
cookie.setHttpOnly(true);
sessionManager.setSessionIdCookie(cookie);
return sessionManager;
} /**
* 缓存管理器 使用Ehcache实现 如果使用redis则注释下面内容!!!!
*/
@Bean
public CacheManager getCacheShiroManager(EhCacheManagerFactoryBean ehcache) {
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManager(ehcache.getObject());
return ehCacheManager;
} /**
* 项目自定义的Realm
*/
@Bean
public ShiroDbRealm shiroDbRealm() {
return new ShiroDbRealm();
} @Bean
public ShiroTockenRealm shiroTockenRealm( ) {
return new ShiroTockenRealm();
} @Bean
public ShiroJwtRealm shiroJwtRealm( ) {
return new ShiroJwtRealm();
} /**
* 系统自带的Realm管理,主要针对多realm
* */
@Bean
public ModularRealmAuthenticator modularRealmAuthenticator(){
ModularRealmAuthenticator modularRealmAuthenticator=new ModularRealmAuthenticator();
modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return modularRealmAuthenticator;
}
/**
* rememberMe管理器, cipherKey生成见{@code Base64Test.java}
*/
@Bean
public CookieRememberMeManager rememberMeManager(SimpleCookie rememberMeCookie) {
CookieRememberMeManager manager = new CookieRememberMeManager();
manager.setCipherKey(Base64.decode("Z3VucwAAAAAAAAAAAAAAAA=="));
manager.setCookie(rememberMeCookie);
return manager;
} /**
* 记住密码Cookie
*/
@Bean
public SimpleCookie rememberMeCookie() {
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
simpleCookie.setHttpOnly(true);
simpleCookie.setMaxAge(7 * 24 * 60 * 60);//7天
return simpleCookie;
} /**
* 在方法中 注入 securityManager,进行代理控制
*/
@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean(DefaultWebSecurityManager securityManager) {
MethodInvokingFactoryBean bean = new MethodInvokingFactoryBean();
bean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
bean.setArguments(new Object[]{securityManager});
return bean;
} /**
* 保证实现了Shiro内部lifecycle函数的bean执行
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
} /**
* 启用shrio授权注解拦截方式,AOP式方法级权限检查
*/
@Bean
@DependsOn(value = "lifecycleBeanPostProcessor") //依赖其他bean的初始化
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
return new DefaultAdvisorAutoProxyCreator();
} @Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
} }

SpringBoot中Shiro缓存使用Redis、Ehcache的更多相关文章

  1. SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理|前后端分离(下)----筑基后期

    写在前面 在上一篇文章<SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理(上)----筑基中期>当中,我们初步实现了SpringBoot整合Shiro ...

  2. Springboot中使用缓存

    在开发中,如果相同的查询条件去频繁查询数据库, 是不是会给数据库带来很大的压力呢?因此,我们需要对查询出来的数据进行缓存,这样客户端只需要从数据库查询一次数据,然后会放入缓存中,以后再次查询时可以从缓 ...

  3. springboot中使用cache和redis

    知识点:springboot中使用cache和redis (1)springboot中,整合了cache,我们只需要,在入口类上加 @EnableCaching 即可开启缓存 例如:在service层 ...

  4. SpringBoot中Shiro使用Pac4j集成CAS认证

    SpringBoot中Shiro使用Pac4j集成CAS认证 Pac4j 简介 Pac4j与Shiro,Spring Security一样都是权限框架,并且提供了OAuth - SAML - CAS ...

  5. Shiro缓存使用Redis、Ehcache、自带的MpCache实现的三种方式实例

    第一种:使用Redis做缓存,将数据存储到redis数据库中 第一步:在项目里面引入redis,配置文件如下: 配置文件:spring_shiro_redis.xml <?xml version ...

  6. SpringBoot 集成Shiro之使用Redis缓存授权认证信息

    因为用户认证与授权需要从数据库中查询并验证信息,但是对于权限很少改变的情况,这样不断从数据库中查询角色验证权限,对整个系统的开销很大,对数据库压力也随之增大.因此可以将用户认证和授权信息都缓存起来,第 ...

  7. SpringBoot(七) SpringBoot中的缓存机制

    随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...

  8. Springboot中的缓存Cache和CacheManager原理介绍

    背景理解 什么是缓存,为什么要用缓存 程序运行中,在内存保持一定时间不变的数据就是缓存.简单到写一个Map,里面放着一些key,value数据,就已经是个缓存了 所以缓存并不是什么高大上的技术,只是个 ...

  9. SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理(上)----筑基中期

    写在前面 通过前几篇文章的学习,我们从大体上了解了shiro关于认证和授权方面的应用.在接下来的文章当中,我将通过一个demo,带领大家搭建一个SpringBoot整合Shiro的一个项目开发脚手架, ...

随机推荐

  1. Java编程思想:Preferences

    import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; public class Test ...

  2. 跨站脚本攻击(反射型xss)笔记(一)

    环境:一个微信端(所以用浏览器演示UI有点变形) 下图是未插任何脚本时的原页面. 按惯例,上一波["><script>alert(1)</script>] 无弹 ...

  3. python函数知识二 动态参数、函数的注释、名称空间、函数的嵌套、global,nonlocal

    6.函数的动态参数 *args,**kwargs:能接受动态的位置参数和动态的关键字参数 *args -- tuple *kwargs -- dict 动态参数优先级:位置参数 > 动态位置参数 ...

  4. JS时间处理,获取天时分秒。以及浏览器出现的不兼容问题

    //获取时间的天,小时,分钟,秒 function ToTime(second) { second = second / ; var result ; ) % ; ) % ; * )); ) { re ...

  5. grep -nr "Base64Decode" * 查找含有某字符的文件

    grep -nr "Base64Decode" * 查找含有某字符的文件

  6. 个人永久性免费-Excel催化剂功能第51波-聚光灯功能,长宽工作表不看错位使用

    Excel的聚光灯功能,笔者是有点看不上,也曾经写文吐槽过这些类似的功能的实用性,但现实可能真的很多小白很需要,大家Excel水平参差不齐,大量的不规范做表习惯,致使此功能使用场景仍然非常广阔.很怀疑 ...

  7. python函数基础-参数-返回值-注释-01

    什么是函数 函数就是有特定功能的工具 # python中有内置函数(python解释器预先封装好的)与自定义函数(用户自定义封装的)之分 为什么要用函数 # 可以减少代码冗余,增加代码复用性 # 使代 ...

  8. vue.js-vue入门教程教你如何html中使用vue(30分钟快速入门)

    前后端分离.微服务框架是当下比较流行的词汇,而vue就是前端框架的佼佼者.下面重点介绍一下vue的用法: vue起步:1.引包    2.启动new Vue({el:目的地,template:模板内容 ...

  9. 完整使用JDBC访问数据库

    Connection con = null; PreparedStatement statement = null; ResultSet res = null; List<Student> ...

  10. session对象和cookie对象的区别

    1.cookie数据存放在客户的浏览器上,session数据放在服务器上2.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session3.ses ...