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. python深入理解类和对象

    1,鸭子类型和多态 当看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那这只鸟就是鸭子 是不是比较混乱,看个例子: # -*- coding:UTF-8 -*- __autor__ = 'zh ...

  2. spring mvc重定向

    spring mvc重定向有三种方法. 1.return new ModelAndView("redirect:/toUrl"); 其中/toUrlt是你要重定向的url. 2.r ...

  3. Yii2增删改查

    Controller <?php namespace frontend\controllers; use frontend\models\User; use yii\data\Paginatio ...

  4. Swift 反射机制,命名空间

    1. 知道 Swift 中有命名空间        - 在同一命名空间下,全局共享!        - 第三方框架使用 Swift 如果直接拖拽到项目中,从属同一个命名空间,很有可能冲突!       ...

  5. Agile PLM 表结构说明

    1.    Activity:项目表class表示大类(关口和活动),subclass表示小类(关口,任务,计划,阶段)subclass=18027:计划(项目),subclass=18028:阶段, ...

  6. Solidity合约间的调用 -Solidity通过合约转ERC20代币

    Solidity通过合约转ERC20代币   ERC20代币并不能像Ether一样使用sendTo.transfer(amt)来转账,ERC20代币只能通过token中定义的transfer方法来转账 ...

  7. vue.$nextTick 解决了哪些问题

    转载:https://www.cnblogs.com/xuewuhen/p/7860989.html $nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $next ...

  8. https 网络传输安全架设

    1:在集群的情况下,不能在tomcat上 架构ssl 而是在总路由nginx上架设具体实现如下截图 非对称加密是当前流行的加密传输方式 证书是什么  . 在浏览器证书查看 证书是访问请求时 https ...

  9. [树状数组+逆序对][NOIP2013]火柴排队

    火柴排队 题目描述 涵涵有两盒火柴,每盒装有n根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑ (ai-bi)2,i=1,2,3,. ...

  10. 14.2.4HTML5约束API验证

    <body> <form> <!-- required属性在提交表单时不能空着 这个属性适用于<input> <textarea> <sel ...