SpringBoot:Shiro 整合 Redis

前言html

前段時間作了一個圖牀的小項目,安全框架使用的是Shiro。爲了使用戶7x24小時訪問,決定把項目由單機升級爲集羣部署架構。可是安全框架shiro只有單機存儲的SessionDao,儘管Shrio有基於Ehcache-rmi的組播/廣播實現,然而集羣的分佈每每是跨網段的,甚至是跨地域的,因此尋求新的方案。

架構

方案java

使用 redis 集中存儲,實現分佈式集羣共享用戶信息,這裏咱們採用第三方開源插件crazycake來實現,pom.xml 引入:
[XML]  純文本查看 複製代碼
?
< dependency >    [/align][align=left]< groupId >org.springframework.boot</ groupId >  [/align][align=left]  < artifactId >spring-boot-starter-data-redis</ artifactId >[/align][align=left]</ dependency >[/align][align=left]< dependency >   [/align][align=left] < groupId >org.crazycake</ groupId >  [/align][align=left]  < artifactId >shiro-redis</ artifactId > [/align][align=left]   < version >3.2.3</ version >[/align][align=left]</ dependecy >
配置 application.properties:
[PowerShell]  純文本查看 複製代碼
?
1
2
3
4
5
6
7
8
9
# Redis# 數據庫索引(默認爲0)redis.database=0
# 服務器地址 變動爲本身的
redis.host=127.0.0.1
# 服務器鏈接端口
redis.port=6379
# 服務器鏈接密碼,若是不設置密碼註釋掉便可
# redis.password=
# 鏈接超時時間(毫秒)
redis.timeout=30000
原本crazycake插件已經實現了RedisManager,可是參數不可配,這裏咱們須要本身重寫一下:
[Java]  純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
public class RedisManager extends WorkAloneRedisManager implements IRedisManager {   
private RedisProperties redis;  
  private JedisPool jedisPool;  
  public RedisManager(RedisProperties redis) {      
  this .redis = redis;    }   
private void init() {      
  synchronized ( this ) {         
   if ( this .jedisPool == null ) {               
this .jedisPool = new JedisPool( this .getJedisPoolConfig(), redis.getHost(), redis.getPort(),                       
redis.getTimeout(), redis.getPassword(), redis.getDatabase());           
}       
}   
}   
@Override  
  protected Jedis getJedis() {       
if ( this .jedisPool == null ) {          
  this .init();       
}       
return this .jedisPool.getResource();   
}}
參數配置 RedisProperties:
[Java]  純文本查看 複製代碼
?
@Data
@ConfigurationProperties (prefix = "redis" )
public class RedisProperties {   
private String host;   
private int port;   
private int timeout;   
private String password;   
private int database;}
配置 ShiroConfig:
[Java]  純文本查看 複製代碼
?
/** * Shiro權限配置 * 必定要配置 @Configuration 和 @EnableConfigurationProperties 註解 */
@Configuration
@EnableConfigurationProperties ({RedisProperties. class })
public class ShiroConfig {   
private RedisProperties redis;   
public ShiroConfig(RedisProperties redis) {       
this .redis = redis;   
}   
@Bean  
  public UserRealm userRealm() {       
return new UserRealm();   
}   
@Bean   
public ShiroFilterFactoryBean shiroFilterFactoryBean (SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
         shiroFilterFactoryBean.setSecurityManager(securityManager);
         shiroFilterFactoryBean.setLoginUrl( "/index.html" );
        shiroFilterFactoryBean.setUnauthorizedUrl( "/403" );
         // 攔截器
         Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        /**
          * 靜態文件
          */
        filterChainDefinitionMap.put( "/file/**" , "anon" );
         /**
          * 登陸註冊
          */
        filterChainDefinitionMap.put( "/register.shtml" , "anon" );
        filterChainDefinitionMap.put( "/login.shtml" , "anon" );
         /**
         * 管理後臺
         */
        filterChainDefinitionMap.put( "/sys/**" , "roles[admin]" );
        filterChainDefinitionMap.put( "/**" , "authc" );
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
     @Bean
     public SessionsSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
         securityManager.setRealm(userRealm());
        securityManager.setCacheManager(cacheManager());
         securityManager.setSessionManager(sessionManager());
        return securityManager;
    }
    @Bean
     public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionIdUrlRewritingEnabled( false );
         sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }
     @Bean
    public ShiroDialect shiroDialect(){
         return new ShiroDialect();
     }
    /**
      * cacheManager 緩存 redis實現
      * @return
      */
     public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
         return redisCacheManager;
    }
     /**
     * 配置shiro redisManager
      * @return
      */
     public RedisManager redisManager() {
         RedisManager redisManager = new RedisManager(redis);
        return redisManager;
    }
     /**
     * RedisSessionDAO shiro sessionDao層的實現
     * 原理就是重寫 AbstractSessionDAO
      * 有興趣的小夥伴自行閱讀源碼
      */
    @Bean
     public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }}

小結redis

是否是很爽,之後重啓應用不再用擔憂用戶投訴了?
更多技術資訊可關注:itheimaGZ公冢號獲取
相關文章
相關標籤/搜索