我的公众号:MarkerHub,Java网站:https://markerhub.com

更多精选文章请点击:Java笔记大全.md

小Hub领读:

集群的分布式场景中,咱们须要把泛滥服务的会话状态保持一致,常见的就是把会话信息保留到redis中实现共享,那么你晓得shiro集成redis实现会话共享有多简略吗?真的只须要4步!


在一些分布式场景中,比方一个简略负载平衡场景,一个nginx,反向代理到两个tomcat,tomcat运行这同样的我的项目,那么这时候,服务的会话须要共享,因为咱们曾经应用了shiro来实现咱们的认证受权逻辑,那么shiro实现登录之后,如何让另外一个服务同时也是登录状态呢?

咱们延用上篇文章的我的项目代码,应用两个端口8080、8081别离启动我的项目。

  • http://localhost:8080
  • http://localhost:8081

有些同学不晓得怎么用idea同一个我的项目别离启动两个端口,其实很简略,只须要在Run/Debug ConfigurationsVM options上,指定启动端口-Dserver.port=8081即可!

ok,别离启动8080和8081我的项目之后,登录8080我的项目,而后拜访8081,发现8081未登录!图示如下:

那么,如何能力8080登录之后,8081也同时实现登录呢?

非凡解决形式

其实在负载平衡集群中,有些人是这样解决问题,给ip指定服务,比方某个用户申请通过nginx反向代理到8080服务,那么nginx上指定ip_hash:根据ip调配形式,那么这个用户就始终拜访同一个服务,不会拜访到8081服务,所以用户就始终是拜访对立服务,所以在用户看来,他就始终是登录状态的。

然而,这是有缺点的,因为ip和服务绑定了,退出这个服务挂了之后,是不会转发到其余服务,所以对这用户来说,就拜访异样。

所以咱们须要应用更罕用的负载平衡策略,比方轮询、权重等。

回顾shiro的架构与组件

ok,进入正题,shiro做会话共享,会话信息能够存储到内存,数据库,或者缓存中间件中,这里咱们应用一个罕用的缓存中间件Redis来保留咱们的会话信息,那么,咱们就须要shiro集成redis。

能够回顾一下之前咱们介绍过的shiro的整体架构:

下面与会话或缓存相干的组件有:

  • Session Manager 会话管理器
  • Session DAO 会话 DAO,将session保留到数据库、缓存等
  • Cache Manager 缓存管理器,权限认证的缓存、用户及权限信息的缓存等

如果只是做会话共享,只是改写Session DAO如同也是能够的,我之前试过,不过既然shiro曾经集成redis,那么数据啥的最好也一起共享吧,防止出现缓存不统一的状况。依照这个逻辑,其实就是重写这3个组件就行了。

shiro-redis整合步骤

那么,有什么曾经写好的shiro集成redis整合我的项目嘛?

这里给大家介绍一个

https://github.com/alexxiyang/shiro-redis/# 文档https://github.com/alexxiyang/shiro-redis/blob/master/docs/README.md# 或者http://alexxiyang.github.io/shiro-redis/

readme.md上有具体的教程,这里咱们间接应用Spring boot starter形式,因为须要写的代码少,间接写写配置就好。

第一步:导入shiro-redis的starter包

<dependency>    <groupId>org.crazycake</groupId>    <artifactId>shiro-redis-spring-boot-starter</artifactId>    <version>3.2.1</version></dependency>

能够看下shiro-redis-spring-boot-starter源码:

能够看出,曾经蕴含了shiro-spring-boot-web-startershiro-redis整合包了,所以之前我的项目中整合进来的shiro-spring-boot-web-starter能够正文掉了。

第二步,依据阐明,readme外面说,如果你没有自定义创立SessionManager or SessionsSecurityManager,那么会主动给你创立,集成实现。然而咱们自定义了realm,所以SecurityManager还是必须要自定义的。

  • com.markerhub.config.ShiroConfig
@Configurationpublic class ShiroConfig {    @Autowired    RedisSessionDAO redisSessionDAO;    @Autowired    RedisCacheManager redisCacheManager;    @Bean    AccountRealm accountRealm() {        return new AccountRealm();    }    @Bean    public SessionManager sessionManager() {        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();        // inject redisSessionDAO        sessionManager.setSessionDAO(redisSessionDAO);        return sessionManager;    }    @Bean    public DefaultWebSecurityManager securityManager(AccountRealm accountRealm, SessionManager sessionManager) {        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();        securityManager.setRealm(accountRealm);        //inject sessionManager        securityManager.setSessionManager(sessionManager);        // inject redisCacheManager        securityManager.setCacheManager(redisCacheManager);        return securityManager;    }    @Bean    public ShiroFilterChainDefinition shiroFilterChainDefinition() {        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();        // logged in users with the 'admin' role        chainDefinition.addPathDefinition("/admin/**", "authc, roles[admin]");        // logged in users with the 'document:read' permission        chainDefinition.addPathDefinition("/docs/**", "authc, perms[document:read]");        chainDefinition.addPathDefinition("/login", "anon");        chainDefinition.addPathDefinition("/doLogin", "anon");        // all other paths require a logged in user        chainDefinition.addPathDefinition("/**", "authc");        return chainDefinition;    }}

相比之前的配置,多了配置了个SessionManager,而后对应配置中注入sessionManager和redisCacheManager。如同我的项目就曾经能够运行啦。

登录胜利之后查看redis中的数据成果如下:

阐明咱们的会话信息曾经保留到redis中啦。而后咱们再换个端口8081启动我的项目,发现8080登录胜利之后,8081服务也是登录胜利状态。

第三步、依据需要调整参数,能够在配置文件中调整的参数我贴出来:

  • application.yml
shiro-redis:  enabled: true  redis-manager:    host: 127.0.0.1:6379

ok,shiro-redis曾经整合结束,是不是挺简略的哈。

留神点

应用这个整合包,有个留神点,如果你应用了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):

restart.include.shiro-redis=/shiro-[\w-\.]+jar

所以,第四步:只须要在resources新建一个文件夹META-INF,而后新建文件spring-devtools.properties,内容为:

restart.include.shiro-redis=/shiro-[\\w-\\.]+jar

成果如下:

结束语

好了,明天先讲到这里吧,shiro系列的文章曾经发了几篇了,前面还有一篇集成单点登录的,而后就完结了哈。这里是MarkerHub,我是小Hub吕一明,快去星标置顶我的公众号吧!


(完)

举荐浏览

Java笔记大全.md

太赞了,这个Java网站,什么我的项目都有!https://markerhub.com

这个B站的UP主,讲的java真不错!