转载

SpringBoot 2.x 开发案例之 Shiro 整合 Redis

点击▲关注 “ 爪哇笔记 ”   给公众号标星置顶

更多精彩 第一时间直达

SpringBoot 2.x 开发案例之 Shiro 整合 Redis

前言

前段时间做了一个图床的小项目,安全框架使用的是 Shiro 。为了使用户 7x24 小时访问,决定把项目由单机升级为集群部署架构。但是安全框架 shiro 只有单机存储的 SessionDao ,尽管 Shrio 有基于 Ehcache-rmi 的组播/广播实现,然而集群的分布往往是跨网段的,甚至是跨地域的,所以寻求新的方案。

架构

SpringBoot 2.x 开发案例之 Shiro 整合 Redis

方案

使用  redis  集中存储,实现分布式集群共享用户信息,这里我们采用第三方开源插件 crazycake 来实现, pom.xml  引入:

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

配置  application.properties

# Redis
# 数据库索引(默认为0)
redis.database=0
# 服务器地址 变更为自己的
redis.host=127.0.0.1
# 服务器连接端口
redis.port=6379
# 服务器连接密码,如果不设置密码注释掉即可
# redis.password=
# 连接超时时间(毫秒)
redis.timeout=30000

本来 crazycake 插件已经实现了 RedisManager ,但是参数不可配,这里我们需要自己重写一下:

  1. public class RedisManager extends WorkAloneRedisManager implements IRedisManager {

  2. private RedisProperties redis;

  3. private JedisPool jedisPool;

  4. public RedisManager(RedisProperties redis) {

  5. this.redis = redis;

  6. }

  7. private void init() {

  8. synchronized(this) {

  9. if (this.jedisPool == null) {

  10. this.jedisPool = new JedisPool(this.getJedisPoolConfig(), redis.getHost(), redis.getPort(),

  11. redis.getTimeout(), redis.getPassword(), redis.getDatabase());

  12. }

  13. }

  14. }

  15. @Override

  16. protected Jedis getJedis() {

  17. if (this.jedisPool == null) {

  18. this.init();

  19. }

  20. return this.jedisPool.getResource();

  21. }

  22. }

参数配置  RedisProperties

  1. @Data

  2. @ConfigurationProperties(prefix = "redis")

  3. public class RedisProperties {

  4. private String host;

  5. private int port;

  6. private int timeout;

  7. private String password;

  8. private int database;

  9. }

配置  ShiroConfig

  1. /**

  2. * Shiro权限配置

  3. * 一定要配置 @Configuration 和 @EnableConfigurationProperties 注解

  4. */

  5. @Configuration

  6. @EnableConfigurationProperties({RedisProperties.class})

  7. public class ShiroConfig {

  8. private RedisProperties redis;

  9. public ShiroConfig(RedisProperties redis) {

  10. this.redis = redis;

  11. }

  12. @Bean

  13. public UserRealm userRealm() {

  14. return new UserRealm();

  15. }

  16. @Bean

  17. public ShiroFilterFactoryBean shiroFilterFactoryBean (SecurityManager securityManager) {

  18. ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

  19. shiroFilterFactoryBean.setSecurityManager(securityManager);

  20. shiroFilterFactoryBean.setLoginUrl("/index.html");

  21. shiroFilterFactoryBean.setUnauthorizedUrl("/403");

  22. // 拦截器

  23. Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

  24. /**

  25. * 静态文件

  26. */

  27. filterChainDefinitionMap.put("/file/**","anon");

  28. /**

  29. * 登录注册

  30. */

  31. filterChainDefinitionMap.put("/register.shtml","anon");

  32. filterChainDefinitionMap.put("/login.shtml","anon");

  33. /**

  34. * 管理后台

  35. */

  36. filterChainDefinitionMap.put("/sys/**", "roles[admin]");

  37. filterChainDefinitionMap.put("/**", "authc");

  38. shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

  39. return shiroFilterFactoryBean;

  40. }

  41. @Bean

  42. public SessionsSecurityManager securityManager() {

  43. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

  44. securityManager.setRealm(userRealm());

  45. securityManager.setCacheManager(cacheManager());

  46. securityManager.setSessionManager(sessionManager());

  47. return securityManager;

  48. }

  49. @Bean

  50. public DefaultWebSessionManager sessionManager() {

  51. DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();

  52. sessionManager.setSessionIdUrlRewritingEnabled(false);

  53. sessionManager.setSessionDAO(redisSessionDAO());

  54. return sessionManager;

  55. }

  56. @Bean

  57. public ShiroDialect shiroDialect(){

  58. return new ShiroDialect();

  59. }

  60. /**

  61. * cacheManager 缓存 redis实现

  62. * @return

  63. */

  64. public RedisCacheManager cacheManager() {

  65. RedisCacheManager redisCacheManager = new RedisCacheManager();

  66. redisCacheManager.setRedisManager(redisManager());

  67. return redisCacheManager;

  68. }

  69. /**

  70. * 配置shiro redisManager

  71. * @return

  72. */

  73. public RedisManager redisManager() {

  74. RedisManager redisManager = new RedisManager(redis);

  75. return redisManager;

  76. }

  77. /**

  78. * RedisSessionDAO shiro sessionDao层的实现

  79. * 原理就是重写 AbstractSessionDAO

  80. * 有兴趣的小伙伴自行阅读源码

  81. */

  82. @Bean

  83. public RedisSessionDAO redisSessionDAO() {

  84. RedisSessionDAO redisSessionDAO = new RedisSessionDAO();

  85. redisSessionDAO.setRedisManager(redisManager());

  86. return redisSessionDAO;

  87. }

  88. }

小结

是不是很爽,以后重启应用再也不用担心用户投诉了?

SpringBoot 2.x 开发案例之 Shiro 整合 Redis

2.x 开发案例之优雅的校验参数

2.x 开发案例之优雅的处理异常

2.x 开发案例之整合HTTP客户端Feign

2.x 开发案例之整合Spring Boot Admin

SpringBoot 2.x 开发案例之 Shiro 整合 Redis

▲一个有温度的公众号,期待与你一起进步

原文  http://mp.weixin.qq.com/s?__biz=MzA3OTUyNjkwMw==&mid=2656653021&idx=1&sn=cf77c8dd559ac6ab64136c3b3f91634d
正文到此结束
Loading...