SpringBoot:Shiro 整合 Redis
阿新 • • 發佈:2020-02-05
前言
前段時間做了一個圖床的小專案,安全框架使用的是Shiro。為了使使用者7x24小時訪問,決定把專案由單機升級為叢集部署架構。但是安全框架shiro只有單機儲存的SessionDao,儘管Shrio有基於Ehcache-rmi的組播/廣播實現,然而叢集的分佈往往是跨網段的,甚至是跨地域的,所以尋求新的方案。架構
方案
< 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 >
|
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
|
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();
}}
|
@Data
@ConfigurationProperties (prefix = "redis" )
public class RedisProperties {
private String host;
private int port;
private int timeout;
private String password;
private int database;}
|
/** * 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;
}}
|
小結
是不是很爽,以後重啟應用再也不用擔心使用者投訴了?