Zuul网关安全开发
# 微服务与资源服务器耦合的弊端
1、资源服务器要向认证服务器进行token验证(uuid形式的token)/oauth/check_token
,当微服务多的时候,会给认证服务器造成压力
2、资源服务器和微服务耦合,业务代码和安全相关的代码杂合在一起,如果token的生成方式更换,则需要全部更改微服务里面的代码,这将是灾难。一般开发人员专注于业务开发即可,安全相关就统一处理
3、多个微服务同时暴露,增加了外部访问的复杂性
# 微服务安全解决方案
原理流程图
网关担任资源服务器的角色,与认证服务器之间进行token校验。同时网关还担任限流、日志等功能
微服务只处理业务代码,安全相关交由网关
客户端请求直接对接网关,再由网关进行负载均衡分发给各个微服务
使用微服务网关还有以下优点:
- 易于监控。可在微服务网关收集监控数据并将其推送到外部系统进行分析。
- 易于认证。可在微服务网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。
- 减少了客户端与各个微服务之间的交互次数。
# 整合zuul
# Zuul简介
Zuul是Netflix开源的微服务网关,它可以和Eureka、Ribbon、Hystrix等组件配合使用。
Zuul的核心是一系列的过滤器,这些过滤器可以完成以下功能。
身份认证与安全;识别每个资源的验证要求,并拒绝那些与要求不符的请求。
审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。
动态路由:动态地将请求路由到不同的后端集群。
压力测试:逐渐增加指向集群的流量,以了解性能。
负载分配:为每一种负载类型分配对应容量,并弃用超岀限定值的请求。
静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群。
多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB ( Elastic Load Balancing) 使用的多样化,以及让系统的边缘更贴近系统的使用者。
Spring Cloud对Zuul进行了整合与增强。目前,Zuul使用的默认HTTP客户端是Apache HTTPClient,也可以使用 RestClient 或者okhttp3.OkHttpClient。
如果想要使用 RestClient, 可以设置ribbon.restclient.enabled=true;想要使用okhttp3.OkHttpClient,可以设置 ribbon .okhttp.enabled= true。
# 1、引starter
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-zuul -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
2
3
4
5
6
@Configuration(proxyBeanMethods = false)
@Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class,
HttpClientConfiguration.class })
@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {}
2
3
4
5
6
7
# 2、写配置加注解@EnableZuulProxy
@EnableCircuitBreaker
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({ZuulProxyMarkerConfiguration.class})
public @interface EnableZuulProxy {}
2
3
4
5
自动引入了 ZuulProxyMarkerConfiguration.Marker
zuul:
routes:
token:
url: http://auth.caofanqi.cn:9020
path: /token/**
order:
url: http://order.caofanqi.cn:9080
path: /order/**
# 定义敏感头
sensitive-headers:
2
3
4
5
6
7
8
9
10
sensitive-headers 设置为空表示没有任何的头对我来说是敏感头。即头里的任何信息都往后转发。如果不设置敏感头的话,请求头中的cookie、Authorization是转发不过去的。
默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并且Zuul的路由规则如下:http://ZUUL_HOST:ZUUL_PORT/serviced/**
会被转发到 serviceld 对应的微服务。
# 3、写过滤器
@Component
public class Oauth2Filter extends ZuulFilter {
// 过滤器类型: pre post error route
@Override
public String filterType() {
return "pre";
}
// 顺序: 限流(0)、认证(1)、审计日志(2)、授权(3)
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
// 过滤器业务代码
@Override
public Object run() throws ZuulException {
return null;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# zuul审计日志过滤器
# zuul限流
# 1、限流配置
注意版本,spring-cloud-zuul-ratelimit 2.2.x没有啥问题,2.4.x会有版本冲突
<!--Zuul限流的相关依赖-->
<!-- https://mvnrepository.com/artifact/com.marcosbarbero.cloud/spring-cloud-zuul-ratelimit -->
<dependency>
<groupId>com.marcosbarbero.cloud</groupId>
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
spring:
application.name: zxp-gateway-zuul
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/security-demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
username: root
password: 123456
jpa:
hibernate:
ddl-auto: update
show-sql: true
zuul:
# 忽略敏感头: Cookie,Set-Cookie,Authorization
sensitive-headers:
routes:
token:
#serviceId: oauth2-auth-server
url: http://localhost:3001
path: /token/**
client8001:
serviceId: eureka-client-8001
path: /client8001/**
client8002:
serviceId: eureka-client-8002
path: /client8002/**
client8003:
serviceId: eureka-client-8003
path: /client8003/**
ratelimit:
enabled: true
repository: jpa # RateLimitRepository.redis
default-policy-list:
- limit: 2 #可选 - 每个刷新时间窗口对应的请求数量限制
quota: 1 #可选- 每个刷新时间窗口对应的请求时间限制(秒)
refresh-interval: 3 # 刷新时间窗口的时间,默认值 (秒)
type: #可选 限流方式
- url
- httpmethod
- origin
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
限流配置见源码RateLimitProperties的属性defaultPolicyList
policyList
,限流规则可以保存到jpa、redis当中,保存在jpa数据库中时,会建立表rate
# 2、自定义限流策略
# 3、记录限流日志异常
# 版本的坑
springboot2.4以上会报错
<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.3.10.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
2
3
4
5
参考笔记
Spring cloud微服务安全实战-4-8Zuul网关安全开发(一) - GASA - 博客园 (cnblogs.com) (opens new window)
开源项目:caofanqi/study-security: 学习安全相关 (github.com) (opens new window)
《Spring Cloud Netflix官方文档》路由和过滤器: Zuul | 并发编程网 – ifeve.com (opens new window)
参考视频: