一土陪、前言
當(dāng)我們的用戶量到達(dá)一定程度的時(shí)候箭窜,單機(jī)的服務(wù)器已經(jīng)支撐不了目前的訪問(wèn)量忍些,我們肯定需要對(duì)服務(wù)器做集群來(lái)提高應(yīng)用的負(fù)載能力.比如我們使用Nginx+Tomcat來(lái)實(shí)現(xiàn)集群,如果使用的是輪詢的測(cè)試撬统,我肯定需要涉及到Session共享的問(wèn)題,解決Session共享有很多種方案,我們選擇的是Shiro+Redis來(lái)實(shí)現(xiàn)缝呕。因?yàn)镾hiro中本身就提供了sessionManager和sessionDAO,我們可以把shiro和redis集成起來(lái)皂甘,把session持久化到Redis中玻驻,然后需要使用的時(shí)候從Redis中獲取對(duì)應(yīng)的session.
二、實(shí)現(xiàn)步驟
步驟一:
在application.properties配置文件中添加Redis相關(guān)的配置
#redis
# Redis服務(wù)器地址
redis.host= localhost
# Redis服務(wù)器連接端口
redis.port= 6379
redis.jedis.pool.max-active=
# 連接池中的最大空閑連接
redis.pool.max-idle= 8
# 連接池中的最小空閑連接
redis.pool.min-idle= 0
# 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制)
redis.pool.max-active= 8
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制)
redis.pool.max-wait= -1
# 連接超時(shí)時(shí)間(毫秒)
redis.timeout= 0
redis.password=
步驟二
我們需要在pom.xml中添加Shiro集成Redis的依賴(lài)
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>2.4.2.1-RELEASE</version>
<exclusions>
<exclusion>
<artifactId>shiro-core</artifactId>
<groupId>org.apache.shiro</groupId>
</exclusion>
</exclusions>
</dependency>
步驟三
在Shiro相關(guān)配置中添加SessionManager和SessionDAO
package cn.wolfcode.saas.pss.config.shiro;
import cn.wolfcode.saas.pss.config.redis.RedisConfig;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created by wolfcode-lanxw
*/
@Configuration
public class ShiroConfig {
/**
* 配置shiro redisManager
* 使用的是shiro-redis開(kāi)源插件
* @return
*/
@Bean
public RedisManager redisManager(RedisConfig redisConfig) {
RedisManager redisManager = new RedisManager();
redisManager.setHost(redisConfig.getHost());
redisManager.setPort(redisConfig.getPort());
redisManager.setExpire(1800);// 配置緩存過(guò)期時(shí)間
redisManager.setTimeout(redisConfig.getTimeout());
return redisManager;
}
@Bean
public RedisSessionDAO redisSessionDAO(RedisManager redisManager) {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager);
return redisSessionDAO;
}
/**
* shiro session的管理
*/
@Bean
public DefaultWebSessionManager redisSessionManager(RedisSessionDAO redisSessionDAO) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(redisSessionDAO);
return sessionManager;
}
@Bean
public RedisCacheManager redisCacheManager(RedisManager redisManager) {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager);
return redisCacheManager;
}
/*
創(chuàng)建安全管理器對(duì)象,關(guān)聯(lián)自定義Realm
*/
@Bean
public DefaultWebSecurityManager securityManager(UserRealm userRealm,DefaultWebSessionManager redisSessionManager,RedisCacheManager redisCacheManager){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
securityManager.setSessionManager(redisSessionManager);
securityManager.setCacheManager(redisCacheManager);
return securityManager;
}
@Bean(name = "shiroFilterFactoryBean")
protected ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, Filter> filterMap = new LinkedHashMap<>();
filterMap.put("authc", new AjaxPermissionsAuthorizationFilter());
shiroFilterFactoryBean.setFilters(filterMap);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/", "anon");
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/error", "anon");
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 開(kāi)啟Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP掃描使用Shiro注解的類(lèi),并在必要時(shí)進(jìn)行安全邏輯驗(yàn)證
* 配置以下兩個(gè)bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可實(shí)現(xiàn)此功能
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
/**
* 開(kāi)啟aop注解支持
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
主要是在DefaultWebSecurityManager中需要配置對(duì)應(yīng)的sessionManager和CacheManager即可.
配置好之后偿枕,當(dāng)?shù)卿浲瓿设邓玻瑫?huì)在Redis中看到對(duì)應(yīng)的key.而且此時(shí)的緩存也交給了redis來(lái)處理了