2021年你还不会Shiro?----9.Shiro利用缓存存储权限信息


前言:
前面的学习以及清楚,我们每调用一次权限的判断,就会默认调用一次自定义Realm中的doGetAuthorizationInfo方法进行过权限验证,但是当用户量与并发量比较高时,再按照这种方式去查询数据库,就会给系统带来很大的压力,让系统的响应变得很慢很,容易降低用户体验。这时候我们就需要使用缓存来存储已经登录的用户信息和用户的权限信息,缓存都是基于内存实现的比数据库快了很多,这样用户进来,直接从缓存中获取信息就行,不用去争抢有限的数据库资源了。

一.思考

上面已经解释了权限信息为什么需要缓存。那么哪些信息适合放入缓存呢

1.哪些信息适合放入缓存?

放入缓存中的信息应该满足一个基本的条件,这些数据不应频繁变动,如果频繁变动了,就不应该被放入缓存中,这样并不能提升系统的性能,而且还会降低性能。

2.可以使用哪些缓存?

在Shiro的使用中,我们可以使用ehCache进行缓存管理,也可以使用市场主流的redis进行缓存管理。其实真实的项目中进本都是使用redis实现缓存,至少笔者做过的四五个使用缓存的项目无论大小,使用的都是redis。所以redis也是我们必须精通的一项技能。

3.Shiro中利用缓存存储认证授权的信息

当Shiro使用缓存进行存储认证与授权的信息时,用户的请求就会变成下图这种,如果使用了缓存就会先去检查缓存中是否有当前用户的缓存信息,如果没有,才会去数据库查询。
在这里插入图片描述

二.使用enCache缓存权限信息

首先看下使用ehCache怎么实现对认证和授权进行缓存管理。

1.导入shiro与ehcache的整合依赖包

这里Shiro使用的版本是1.5.3,shiro-ehcache整合包与Shiro的版本一致,这里也选择1.5.3版本。

	<dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-ehcache</artifactId>
          <version>1.5.3</version>
      </dependency>

2.开启缓存

那么在哪开启缓存使用呢?未使用缓存时,Realm的数据获取来源只有是数据库,开启后Realm的数据来源就变成了数据库和缓存。所以既然是Realm来管理数据,肯定是在Realm中开启了。我们在注入自定义Realm中这样开启缓存。如下:

@Bean
    public FirstRealm getRealm(){
    
    
        FirstRealm firstRealm = new FirstRealm();
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(2048);
//        下面的写法也是正常的,不过现在都是使用上面的写法,下面的写法已经是不推荐使用的了。
//        Md5CredentialsMatcher md5CredentialsMatcher = new Md5CredentialsMatcher();
//        md5CredentialsMatcher.setHashIterations(2048);
        firstRealm.setCredentialsMatcher(hashedCredentialsMatcher);

        //开启缓存
        firstRealm.setCachingEnabled(true);//开启全局的缓存管理
        firstRealm.setAuthenticationCachingEnabled(true);//开启认证缓存
        firstRealm.setAuthorizationCachingEnabled(true);//开启授权缓存
        firstRealm.setAuthenticationCacheName("authenticationCache");//设置缓存名称--认证
        firstRealm.setAuthorizationCacheName("authorizationCache");//设置缓存名称--授权
        firstRealm.setCacheManager(new EhCacheManager());
        return firstRealm;
    }

就像上方代码这样,我们首先需要为自定义Realm设置启用缓存,然后再分别为认证和授权开启缓存。后面又设置了缓存名称,这个其实可以省略。最后告诉自定义Realm使用哪种缓存实现。这里是使用的EhCacheManager。

3.验证缓存效果

我们知道,我们在未使用缓存时每调用一次授权的判断就会触发doGetAuthorizationInfo方法。如下所示刷新页面调用了多次授权方法。
在这里插入图片描述

扫描二维码关注公众号,回复: 13147036 查看本文章

我们使用缓存就是为了防止重复调用,假如开启缓存后,只调用一次授权操作就是我们理想的状态了。验证如下:
在这里插入图片描述
可以看到即使我们多次刷新页面,后台依然只调用了一次授权的操作,这样我们就实现了授权信息的缓存管理,当然了这里只是一个入门的展示。要是想要使用encache,还需要为ehcahe增加很多的配置,失效时间什么的。不过shiro的缓存集成真正会使用的还是redis进行,下一篇会总结redis的集成,并结合笔者正在做的一个shiro项目进行解读。

三.总结

这篇主要是总结了如何初步使用缓存实现授权的管理,其实经笔者验证
授权的缓存默认就是开启的,所以其实我们只使用一行代码就是可以实现授权的缓存功能如图所示,只需要为自定义Realm设置一个缓存管理器即可。仅仅使用了一行下面的代码:

firstRealm.setCacheManager(new EhCacheManager());

我们并没有去设置开启全局缓存,也未设置开启授权缓存这些都是开启了的。
在这里插入图片描述
我们验证下授权缓存有没有正常生效:
在这里插入图片描述
登录进入系统后,点击了多次的刷新后台只调用了一次授权的验证,显然缓存是生效的,到这里如果就确定的就说授权缓存是默认开启的其实也是不严谨的。我们注释掉这一样代码。自定义Realm不对授权的信息做任何操作,我们再来看下是否开启了授权缓存,如下图

在这里插入图片描述
很显然是开启了的,因此授权的缓存是默认开启的。我们若是只是为授权实现缓存其实一行代码就可以实现,但是现实是不可能只为授权提供缓存的。不过我们可以确定的是上方示例中开启全局缓存的代码肯定是多可以省略的,我们已经验证全局缓存和授权缓存默认都是开启的,因此若是想要偷懒,那么我们至少还是要开启认证的缓存的。这样就可以正常使用缓存了,代码就可以精简为如下:

@Bean
    public FirstRealm getRealm(){
    
    
        FirstRealm firstRealm = new FirstRealm();
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(2048);
//        下面的写法也是正常的,不过现在都是使用上面的写法,下面的写法已经是不推荐使用的了。
//        Md5CredentialsMatcher md5CredentialsMatcher = new Md5CredentialsMatcher();
//        md5CredentialsMatcher.setHashIterations(2048);
        firstRealm.setCredentialsMatcher(hashedCredentialsMatcher);

        //开启缓存
//        firstRealm.setCachingEnabled(true);//开启全局的缓存管理
        firstRealm.setAuthenticationCachingEnabled(true);//开启认证缓存
//        firstRealm.setAuthorizationCachingEnabled(true);//开启授权缓存
        firstRealm.setAuthenticationCacheName("authenticationCache");//设置缓存名称--认证
        firstRealm.setAuthorizationCacheName("authorizationCache");//设置缓存名称--授权
        firstRealm.setCacheManager(new EhCacheManager());
        return firstRealm;
    }

猜你喜欢

转载自blog.csdn.net/m0_46897923/article/details/115313181