并不复杂,只需4步搞定Shiro集成redis实现会话共享 - Go语言中文社区

并不复杂,只需4步搞定Shiro集成redis实现会话共享


推荐阅读:

https://blog.csdn.net/m0_46995061/article/details/106124211

https://blog.csdn.net/m0_46995061/article/details/106243292

https://blog.csdn.net/m0_46995061/article/details/106470873

 

集群的分布式场景中,我们需要把众多服务的会话状态保持一致,常见的就是把会话信息保存到redis中实现共享,那么你知道shiro集成redis实现会话共享有多简单吗?真的只需要4步!


在一些分布式场景中,比如一个简单负载均衡场景,一个nginx,反向代理到两个tomcat,tomcat运行着同样的项目,那么这时候,服务的会话需要共享,因为我们已经使用了shiro来完成我们的认证授权逻辑,那么shiro完成登录之后,如何让另外一个服务同时也是登录状态呢?

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

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

有些同学不知道怎么用idea同一个项目分别启动两个端口,其实很简单,只需要在 Run/DebugConfigurations的 VM options上,指定启动端口 -Dserver.port=8081即可!

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

ok,分别启动8080和8081项目之后,登录8080项目,然后访问8081,发现8081未登录!图示如下:

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

那么,如何才能8080登录之后,8081也同时完成登录呢?

特殊解决方式

其实在负载均衡集群中,有些人是这样解决问题,给ip指定服务,比如某个用户请求经过nginx反向代理到8080服务,那么nginx上指定 ip_hash:依据ip分配方式,那么这个用户就一直访问同一个服务,不会访问到8081服务,所以用户就一直是访问统一服务,所以在用户看来,他就一直是登录状态的。

但是,这是有缺陷的,因为ip和服务绑定了,加入这个服务挂了之后,是不会转发到其他服务,所以对这用户来说,就访问异常。

所以我们需要使用更常用的负载均衡策略,比如轮询、权重等。

回顾shiro的架构与组件

ok,进入正题,shiro做会话共享,会话信息可以存储到内存,数据库,或者缓存中间件中,这里我们使用一个常用的缓存中间件Redis来保存我们的会话信息,那么,我们就需要shiro集成redis。

可以回顾一下之前我们介绍过的shiro的整体架构:

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

上面与会话或缓存相关的组件有:

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

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

shiro-redis整合步骤

那么,有什么已经写好的shiro集成redis整合项目吗?

这里给大家介绍一个

1.  `https://github.com/alexxiyang/shiro-redis/`

2.  `# 文档`

3.  `https://github.com/alexxiyang/shiro-redis/blob/master/docs/README.md`

4.  `# 或者`

5.  `http://alexxiyang.github.io/shiro-redis/`

readme.md上有详细的教程,这里我们直接使用 Springboot starter方式,因为需要写的代码少,直接写写配置就好。

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

1.  `<dependency>`

2.  `<groupId>org.crazycake</groupId>`

3.  `<artifactId>shiro-redis-spring-boot-starter</artifactId>`

4.  `<version>3.2.1</version>`

5.  `</dependency>`

可以看下 
shiro-redis-spring-boot-starter源码:

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

可以看出,已经包含了 
shiro-spring-boot-web-starter与 shiro-redis整合包了,所以之前项目中整合进来的 
shiro-spring-boot-web-starter可以注释掉了。

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

第二步,根据说明,readme里面说,如果你没有自定义创建SessionManager or SessionsSecurityManager,那么会自动给你创建,集成完成。但是我们自定义了realm,所以SecurityManager还是必须要自定义的。

  • com.markerhub.config.ShiroConfig
1.  `@Configuration`

2.  `public  class  ShiroConfig  {`

4.  `@Autowired`

5.  `RedisSessionDAO redisSessionDAO;`

7.  `@Autowired`

8.  `RedisCacheManager redisCacheManager;`

10.  `@Bean`

11.  `AccountRealm accountRealm()  {`

12.  `return  new  AccountRealm();`

13.  `}`

15.  `@Bean`

16.  `public  SessionManager sessionManager()  {`

17.  `DefaultWebSessionManager sessionManager =  new  DefaultWebSessionManager();`

19.  `// inject redisSessionDAO`

20.  `sessionManager.setSessionDAO(redisSessionDAO);`

21.  `return sessionManager;`

22.  `}`

24.  `@Bean`

25.  `public  DefaultWebSecurityManager securityManager(AccountRealm accountRealm,  SessionManager sessionManager)  {`

26.  `DefaultWebSecurityManager securityManager =  new  DefaultWebSecurityManager();`

27.  `securityManager.setRealm(accountRealm);`

29.  `//inject sessionManager`

30.  `securityManager.setSessionManager(sessionManager);`

32.  `// inject redisCacheManager`

33.  `securityManager.setCacheManager(redisCacheManager);`

35.  `return securityManager;`

36.  `}`

38.  `@Bean`

39.  `public  ShiroFilterChainDefinition shiroFilterChainDefinition()  {`

40.  `DefaultShiroFilterChainDefinition chainDefinition =  new  DefaultShiroFilterChainDefinition();`

42.  `// logged in users with the 'admin' role`

43.  `chainDefinition.addPathDefinition("/admin/**",  "authc, roles[admin]");`

45.  `// logged in users with the 'document:read' permission`

46.  `chainDefinition.addPathDefinition("/docs/**",  "authc, perms[document:read]");`

48.  `chainDefinition.addPathDefinition("/login",  "anon");`

49.  `chainDefinition.addPathDefinition("/doLogin",  "anon");`

51.  `// all other paths require a logged in user`

52.  `chainDefinition.addPathDefinition("/**",  "authc");`

53.  `return chainDefinition;`

54.  `}`

55.  `}`

相比之前的配置,多了配置了个SessionManager,然后对应配置中注入sessionManager和redisCacheManager。好像项目就已经可以运行了。

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

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

说明我们的会话信息已经保存到redis中啦。然后我们再换个端口8081启动项目,发现8080登录成功之后,8081服务也是登录成功状态。

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

第三步、根据需求调整参数,可以在配置文件中调整的参数我贴出来:

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

  • application.yml
1.  `shiro-redis:`

2.  `enabled:  true`

3.  `redis-manager:`

4.  `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,内容为:

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

效果如下:

并不复杂,只需4步搞定Shiro集成redis实现会话共享

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_46995061/article/details/106751848
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-28 01:23:03
  • 阅读 ( 1684 )
  • 分类:Redis

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢