API 网关的出现的原因是微服务架构的出现,不同的微服务一般会有不同的服务地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性。
  • 存在跨域请求,在一定场景下处理相对复杂。
  • 认证复杂,每个服务都需要独立认证。
  • 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施。
  • 某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难。

网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 API 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 API 网关来做 ,所以网关的性能,高可用,安全性都是至关重要的。

备注Spring Cloud 微服务中搭建 OAuth2.0 认证授权服务

常用网关有哪些 ?

Nginx、Kong、ZUUL、Spring Cloud Gateway(Spring Cloud 官方)、Linkerd 等

Spring Cloud Zuul

Zuul 是 Netflix 开源的微服务网关组件,它可以和 Eureka、Ribbon、Hystrix 等组件配合使用。Zuul 的核心是一系列的过滤器 (比如:动态路由)。Spring Cloud Zuul 对 Zuul 进行了整合 ,从而更方便的与 Spring Cloud 一起使用。

Zuul1

Zuul1 是基于 Servlet 框架构建,采用的是阻塞和多线程方式,即一个线程处理一次连接请求,这种方式在内部延迟严重、设备故障较多情况下会引起存活的连接增多和线程增加的情况发生。

Zuul2

Zuul2 与 Zuul1 最大的区别是它运行在异步和无阻塞框架上,每个 CPU 核一个线程,处理所有的请求和响应,请求和响应的生命周期是通过事件和回调来处理的,这种方式减少了线程数量,因此开销较小。又由于数据被存储在同一个 CPU 里,可以复用 CPU 级别的缓存,前面提及的延迟和重试风暴问题也通过队列存储连接数和事件数方式减轻了很多(较线程切换来说轻量级很多,自然消耗较小)。这一变化一定会大大提升性能。

注:zuul 2.0 版本 Spring Cloud 官方现阶段不打算集成,官方还是推荐使用 Spring Cloud Gateway

性能

可以参考:纠错帖:Zuul & Spring Cloud Gateway & Linkerd性能对比 ,简单来说,Zuul 1.x 是一个基于阻塞 IO 的 API Gateway,另外 Spring Cloud Gateway 性能很好。

高可用

一般生产环境需要将多个 Zuul 节点注册到 Eureka Server 上,就可以实现 Zuul 的高可用。事实上,这种情况下的高可用和其他服务做高可用(例如:Eurka Server 集群)的方案没有什么区别。当 Zuul 客户端注册到 Eureka Server 上时,Zuul 客户端会自动从 Eureka Server 查询 Zuul Server 列表,然后使用负载均衡组件(例如: Ribbon)请求 Zuul 集群。另外的方式也可以使用 Nginx 或者硬件 F5 的来实现。

安全性

Spring Cloud 的微服务化后,一般可以使用 Spring Cloud Security 结合 OAuth2.0,生成的 Token 采用 JWT 来验证票据,但 Spring Cloud Security 暂时还不支持 OpenID Connect 协议。Zuul 将自己注册为 Eureka 服务治理下,同时也从 Eureka 服务治理中获得所有其他微服务的实例信息。通过搭建独立的 OAuth2 认证授权服务,将微服务单独剥离出来,这些认证与微服务自己的业务并没有太大的关系,所以这些功能完全可以独立成一个单独的服务存在。独立出来之后,并不是给每个微服务调用(业务服务一般在内网),而是通过 API网关进行统一调用,来对微服务接口做前置过滤,实现对分布式系统中的其他的微服务接口的拦截和安全校验。

创建 Zuul 网关服务

Maven

        <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>
@SpringBootApplication
//@EnableOAuth2Sso
@EnableZuulProxy
public class MicrosrvZuulGatewayApplication { public static void main(String[] args) {
SpringApplication.run(MicrosrvZuulGatewayApplication.class, args);
}
}

application.yml

spring:
application:
name: microsrv-zuul-gateway server:
port: 5555 eureka:
instance:
preferIpAddress: true
client:
serviceUrl:
defaultZone: http://10.255.131.162:8000/eureka/,http://10.255.131.163:8000/eureka/,http://10.255.131.164:8000/eureka/ zuul:
host:
connect-timeout-millis: 20000
socket-timeout-millis: 20000
ignoredServices: '*'
prefix: /api # 设置一个公共的前缀
routes:
auth-service:
path: /auth/**
sensitiveHeaders:
serviceId: idsrv-server
order-service:
path: /order/**
sensitiveHeaders:
serviceId: order-service
add-proxy-headers: true

因为使用 Eureka 来服务发现,所以请求URL格式形如 /service-id/** 会被自动转发到在 Eureka Server 上注册的 service id 为“service-id”的微服务应用上。例如上面我们定义了两个路由规则,比如将“order-service”的请求转发到相应 service-id 注册的服务上,也可以通过修改 zuul.prefix=/api 配置来配置全局的前缀地址。默认 Eureka Server会暴露所有注册在它上面的微服务。你可以使用 zuul.ignored-services 属性来禁止这种行为,且只有显式配置的服务才会被暴露。

Zuul  整合 OAuth2.0 认证授权

Zuul 整合 OAuth2.0 有两种思路,一种是授权服务器采用 JwtToken 统一在网关层使用公钥验证票据,判断权限等操作;另一种是让资源端处理,网关只做路由转发。

资源端配置

maven

<!-- oauth2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>

Spring Boot

@SpringBootApplication
@EnableResourceServer
public class DemoApplication { public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
} @RestController
public class AccountController { @GetMapping("/principal")
@PreAuthorize("hasAnyAuthority('user')")
public Principal user(Principal principal) {
return principal;
} @GetMapping("/query")
@PreAuthorize("hasAnyAuthority('all')")
public String all () {
return "具有 all 权限";
}
}

application.yml

logging:
level:
org.springframework: DEBUG server:
port: 5000 security:
oauth2:
resource:
# prefer-token-info: true
# user-info-uri: http://localhost:8080/api/v1/users/principal
# token-info-uri: http://localhost:8080/oauth/check_token
jwt:
# key-uri: http://localhost:8080/oauth/token_key
key-value: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm4irSNcR7CSSfXconxL4
g4M4j34wTWdTv93ocMn4VmdB7rCBU/BlxXtBUf/cgLIgQhQrAPszSZSmxiEXCOkG
Pr4aQBQuPgmNIR95Dhbzw/ZN0BnecAt3ZfkkDBHv8kH3kR/jYGTdwrxKeDgXGljN
sTRhbjuASxPG/Z6gU1yRPCsgc2r8NYnztWGcDWqaobqjG3/yzFmusoAboyV7asIp
o4yk378LmonDNwxnOOTb2Peg5PeelwfOwJPbftK1VOOt18zA0cchw6dHUzq9NlB8
clps/VdBap9BxU3/0YoFXRIc18nyzrWo2BcY2KQqX//AJC3OAfrfDmo+BGK8E0mp
8wIDAQAB
-----END PUBLIC KEY-----

最后可以在 Zuul 上启用  @EnableOAuth2Sso 注解作为 OAuth2.0 的一个客户端(非必须),这样当用户访问到网关没有授权的话,会跳转到授权服务器登录授权。

security:
oauth2:
client:
access-token-uri:http://localhost:8080/oauth/token
user-authorization-uri: http://localhost:8080/oauth/authorize
client-id: client_test
client-secret: secret_test
resource:
user-info-uri: http://localhost:8080/api/v1/users/principal
prefer-token-info: false

REFER:

https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/

Spring Cloud Zuul 网关使用与 OAuth2.0 认证授权服务的更多相关文章

  1. Owin中间件搭建OAuth2.0认证授权服务体会

    继两篇转载的Owin搭建OAuth 2.0的文章,使用Owin中间件搭建OAuth2.0认证授权服务器和理解OAuth 2.0之后,我想把最近整理的资料做一下总结. 前两篇主要是介绍概念和一个基本的D ...

  2. Spring Cloud 微服务中搭建 OAuth2.0 认证授权服务

    在使用 Spring Cloud 体系来构建微服务的过程中,用户请求是通过网关(ZUUL 或 Spring APIGateway)以 HTTP 协议来传输信息,API 网关将自己注册为 Eureka ...

  3. 创建swagger的springboot-stater,并在spring cloud zuul网关中引入

    Swagger 是一款RESTFUL接口的.基于YAML.JSON语言的文档在线自动生成.代码自动生成的工具. 通过在controller中添加注解,即可轻易实现代码文档化. Swagger提供ui界 ...

  4. Spring cloud Zuul网关异常处理

    Spring cloud Zuul网关异常处理 一 异常测试: 1> 创建一个pre类型的过滤器,并在该过滤器的run方法实现中抛出一个异常.比如下面的实现,在run方法中调用的doSometh ...

  5. Spring Cloud Security OAuth2.0 认证授权系列(一) 基础概念

    世界上最快的捷径,就是脚踏实地,本文已收录[架构技术专栏]关注这个喜欢分享的地方. 前序 最近想搞下基于Spring Cloud的认证授权平台,总体想法是可以对服务间授权,想做一个基于Agent 的无 ...

  6. Spring Security OAuth2.0认证授权四:分布式系统认证授权

    Spring Security OAuth2.0认证授权系列文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授 ...

  7. Spring Security OAuth2.0认证授权二:搭建资源服务

    在上一篇文章[Spring Security OAuth2.0认证授权一:框架搭建和认证测试](https://www.cnblogs.com/kuangdaoyizhimei/p/14250374. ...

  8. Spring Security OAuth2.0认证授权五:用户信息扩展到jwt

    历史文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二:搭建资源服务 Spring Security OA ...

  9. Spring Security OAuth2.0认证授权六:前后端分离下的登录授权

    历史文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二:搭建资源服务 Spring Security OA ...

随机推荐

  1. FortiGate上架前准备

    1.收集信息 1.网络拓扑信息(了解网络拓扑信息有助于网络方案的规划) 2.环境信息(了解部署位置.部署模式.最大吞吐.最大用户数有助于对设备性能的评估) 3.客户需求,对FortiGate部署的功能 ...

  2. 796. Rotate String旋转字符串

    [抄题]: We are given two strings, A and B. A shift on A consists of taking string A and moving the lef ...

  3. [leetcode]34.Find First and Last Position of Element in Sorted Array找区间

    Given an array of integers nums sorted in ascending order, find the starting and ending position of ...

  4. [leetcode]45. Jump Game II青蛙跳(跳到终点最小步数)

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  5. java_22 Map接口

    1Map Collection是孤立存在的,向集合中存储元素是一个一个放进去的 Map中的集合存储是成对的,可以通过键找到值.即将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值 ...

  6. Python项目--Scrapy框架(一)

    环境 win8, python3.7, pycharm 正文 1.Scrapy框架的安装 在cmd命令行窗口执行: pip install Scrapy 即可完成Scrapy框架的安装 2. 创建Sc ...

  7. java编译时出现——注:使用了未经检查或不安全的操作。注:有关详细信息,请使用 -Xlint:unchecked 重新编译

    网上说是泛型问题 private List<Product> products = new ArrayList<Product>(); 这种用法绝对没错!(因为是照着书写的)在 ...

  8. robotframework手机号随机产生脚本

    首先,要导入使用库 random; ${phone} Evaluate random.choice(['139','188','185','136','158','151'])+"" ...

  9. 通过flask的request对象获取url

    测试了一下:通过发送 GET 到 http://127.0.0.1:5000/test/a?x=1, 后台输出为(官网说明): 1 request.path: /test/a 2 request.ho ...

  10. 页面仔初窥"前端工程化"

    今天看了几篇前端界的一位大牛--张云龙的文章,其中一篇在自己的理解范围内看得懂一些,有所收获,说的是前端工程化的事,看完算是对前端工程形成了一个模糊的概念. 现在我所接触到的前端开发,还是张云龙大神所 ...