–基本:
依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
启动类
@EnableZuulProxy//开启zuul网关功能
yml
server:
port: 8080 #端口
spring:
application:
name: api-zuul-server #服务名称
##路由配置
zuul:
routes:
#已商品微服务
product-service: #路由id,随便写
path: /product-service/** #映射路径 #localhost:8080/product-service/sxxssds
url: http://localhost:9001 #映射路径对应的实际微服务url地址
stripPrefix: false #这个是为了免得自动加前缀,避免/aaa/aaa这种方式访问
–更进:
依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
启动类
@EnableZuulProxy//开启zuul网关功能
@EnableDiscoveryClient//eureka的服务发现
yml
server:
port: 8080 #端口
spring:
application:
name: api-zuul-server #服务名称
##路由配置
zuul:
routes:
#已商品微服务
product-service: #路由id,随便写
path: /product-service/** #映射路径 #localhost:8080/product-service/sxxssds
url: http://localhost:9001 #映射路径对应的实际微服务url地址
serviceId: service-product #配置转发的微服务的服务名称
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
这样就不需要可以配置uri,更换product的ip就不需要更换yml,只要你服务中心ip没变就好。
–再更进:
##路由配置
zuul:
routes:
product-service: #路由id,随便写
#如果路由id 和 对应的微服务的serviceId一致的话
service-product: /product-service/**
#zuul中的默认路由配置
#如果当前的微服务名称 service-product , 默认的请求映射路径 /service-product/**
# /service-order/
自定义过滤器:

- PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- ERROR:在其他阶段发生错误时执行该过滤器。
正常流程:
请求到达首先会经过pre类型过滤器,而后到达routing类型,进行路由,请求就到达真正的服务提供者,执行请求,返回结果后,会到达post过滤器。而后返回响应。
异常流程:
整个过程中,pre或者routing过滤器出现异常,都会直接进入error过滤器,再error处理完毕后,会将请求交给POST过滤器,最后返回给用户。
如果是error过滤器自己出现异常,最终也会进入POST过滤器,而后返回。
如果是POST过滤器出现异常,会跳转到error过滤器,但是与pre和routing不同的时,请求不会再到达POST过滤器了。
不同过滤器的场景:
请求鉴权:一般放在pre类型,如果发现没有访问权限,直接就拦截了
异常处理:一般会在error类型和post类型过滤器中结合来处理。
服务调用时长统计:pre和post结合使用。
过滤器(身份认证,重点!):
/**
* 自定义的zuul过滤器 继承抽象父类
*/
@Component
public class LoginFilter extends ZuulFilter {
/**
* 定义过滤器类型
* pre、routing、post、error
*/
public String filterType() { return "pre"; }
/**
* 指定过滤器的执行顺序,返回值越小,执行顺序越高
*/
public int filterOrder() { return 1; }
/**
* 当前过滤器是否生效。true : 使用此过滤器、false : 不使用此过滤器
*/
public boolean shouldFilter() { return true; }
/**
* 指定过滤器中的业务逻辑
* 身份认证:
* 1.所有的请求需要携带一个参数 : access-token
* 2.获取request请求
* 3.通过request获取参数access-token
* 4.判断token是否为空
* 4.1 token==null : 身份验证失败
* 4.2 token!=null : 执行后续操作
* 在zuul网关中,通过RequestContext的上下问对象,可以获取对象request对象
*/
public Object run() throws ZuulException {
//1.获取zuul提供的上下文对象RequestContext
RequestContext ctx = RequestContext.getCurrentContext();
//2.从RequestContext中获取request
HttpServletRequest request = ctx.getRequest();
//3.获取请求参数access-token
String token = request.getParameter("access-token");
//4.判断
if (token ==null) {
//4.1 如果token==null ,拦截请求,返回认证失败
ctx.setSendZuulResponse(false); // 拦截请求
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
//4.2 如果token!=null ,继续后续操作
return null;
}
}

自定义过滤器(Shiro+Redis):
/**
* 自定义过滤器的
*/
@Component
public class LoginFilter extends ZuulFilter {
/**
* 定义过滤器类型:pre、routing、error、post
* 本过滤器执行时刻:路由请求前、路由请求时、异常时、前面三者之后的收拾收尾
*/
@Override
public String filterType() {
return "pre";
}
/**
* 定义过滤器的优先级。数字越小,优先级越高的
*/
@Override
public int filterOrder() {
return 2;
}
/**
* boolean类型判断过滤器是否需要执行
*/
@Override
public boolean shouldFilter() {
//假如不执行此过滤器(暂时作废)则false
return true;
}
/**
* 重点:具体业务在此完成
*/
@Override
public Object run() throws ZuulException {
System.out.println("执行了loginFilter的run方法");
return null;
}
}
下面加深部分均在shiro配置包里声明配置,具体内容结合shiro配置来看
@Configuration
public class ShiroConfiguration {
//创建Realm
@Bean
public IhrmRealm getRealm() {
return new UserRealm();
}
//创建安全管理器
@Bean(name = "securityManager")
public SecurityManager getSecurityManager(IhrmRealm customRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(customRealm);
//讲自定义的会话管理器注册到安全管理器
securityManager.setSessionManager(redisResessionManager());
//将自定义的redis缓存管理器注册到安全管理器中
securityManager.setCacheManager(redisCacheManager());
return securityManager;
}
//配置过滤器工厂
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
//web中,shiro进行权限控制全部是通过一组过滤器集合进行控制
//创建过滤器工厂
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
// //预检请求拦截器,为了预防无法得到header
// factoryBean.getFilters().put("authc", new ShiroHeaderFilter());
//设置安全管理器
factoryBean.setSecurityManager(securityManager);
//通用配置(跳转登录页面,未授权跳转的页面)
factoryBean.setLoginUrl("/autherror?code=1");
factoryBean.setUnauthorizedUrl("/autherror?code=2");
/**
* 设置过滤器集合,有顺序的map
* key=url拦截地址,value=过滤器类型
*/
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/sys/login","anon");//此地址允许匿名
filterMap.put("/autherror","anon");//此地址允许匿名
filterMap.put("/sys/faceLogin/**","anon");//此地址允许匿名
//swagger
filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/swagger-resources/**", "anon");
filterMap.put("/v2/**", "anon");
filterMap.put("/webjars/**", "anon");
filterMap.put("/**", "authc");//必须认证
factoryBean.setFilterChainDefinitionMap(filterMap);
return factoryBean;
}
//开启注解支持
@Bean(name = "authorizationAttributeSourceAdvisor")
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
@Bean(name = "defaultAdvisorAutoProxyCreator")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);//cglib方式
return defaultAdvisorAutoProxyCreator;
}
//redis的控制器,操作控制器(jar里有,不用自己写的)
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost("47.115.203.188");
redisManager.setPort(6604);
redisManager.setPassword("flowerpower");
return redisManager;
}
//缓存管理器
public RedisCacheManager redisCacheManager() {
RedisCacheManager cacheManager = new RedisCacheManager();
cacheManager.setRedisManager(redisManager());
return cacheManager;
}
//sessionDao
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO sessionDAO = new RedisSessionDAO();
sessionDAO.setRedisManager(redisManager());
return sessionDAO;
}
//自定义的会话管理器了
public DefaultWebSessionManager redisResessionManager() {
CustomSessionManager sessionManager = new CustomSessionManager();
sessionManager.setSessionDAO(redisSessionDAO());
//禁用cookie,禁用url重写(太难看?)
sessionManager.setSessionIdCookieEnabled(false);
sessionManager.setSessionIdUrlRewritingEnabled(false);
return sessionManager;
}
}
zuul:
routes:
ihrm-company:
path: /company/**
serviceId: ihrm-company
stripPrefix: false #不删除请求前缀
#处理敏感头信息
sentiviteHeaders: #指定路由的敏感头设置为空
customSensitiveHeaders: true #对指定路由开启自定义敏感头