苏州网站推广,招标网公告,wordpress app制作,网上推广引流的有用吗?文章目录 前言为什么需要网关以及网关的作用网关的技术实现 一、Gateway 网关的搭建1.1 创建 Gateway 模块1.2 引入依赖1.3 配置网关1.4 验证网关是否搭建成功1.5 微服务结构分析 二、Gateway 断言工厂2.1 Spring 提供的断言工厂2.2 示例#xff1a;设置断言工厂 三、Gateway … 文章目录 前言为什么需要网关以及网关的作用网关的技术实现 一、Gateway 网关的搭建1.1 创建 Gateway 模块1.2 引入依赖1.3 配置网关1.4 验证网关是否搭建成功1.5 微服务结构分析 二、Gateway 断言工厂2.1 Spring 提供的断言工厂2.2 示例设置断言工厂 三、Gateway 路由过滤器及其工厂3.1 路由过滤器 GatewayFilter3.2 路由过滤器工厂 GatewayFilter Factory3.3 示例添加过滤器工厂3.4 默认过滤器 四、Gateway 全局过滤器4.1 全局过滤器的概念和作用4.2 GlobalFilter 接口定义4.3 示例定义全局过滤器进行用户身份验证 五、过滤器链的执行顺序5.1 过滤器链执行过程5.2 过滤器的排序规则5.3 为什么三种不同的过滤器可以进行排序形成过滤器链 六、跨域问题6.1 什么是跨越问题6.2 演示跨越问题6.3 使用 Gateway 解决跨域问题6.3 使用 Gateway 解决跨域问题 前言
为什么需要网关以及网关的作用
在微服务架构中网关是至关重要的组件具有多重职责为整个系统提供了一系列关键功能。从下面的微服务结构图中我们可以明确网关的几项主要作用
微服务结构图 请求过滤与安全 用户的所有请求首先经过网关这使得网关成为系统的第一道防线。通过对传入请求的过滤、验证和安全策略的实施网关确保只有合法的请求能够访问内部的微服务。 路由与负载均衡 网关具有路由功能能够将收到的请求正确地分发给相应的微服务。这种路由机制使得系统更加灵活同时网关还结合了负载均衡的特性确保各个微服务能够平衡地处理请求提升系统的性能和可用性。 统一的接入点 作为系统的入口网关提供了一个统一的接入点简化了客户端与微服务之间的通信。客户端只需与网关进行交互而无需直接与各个微服务打交道从而降低了系统的复杂性。 请求转换与聚合 在实际应用中某些信息可能分布在多个微服务中。网关的聚合和转换功能使得它能够从多个微服务中收集数据然后以符合客户端期望的格式返回。此外网关还可以处理请求和响应的转换以适应不同微服务的接口。 请求限流与熔断 网关在系统入口处实施请求限流和熔断机制以防止不良请求对整个系统造成影响。通过在网关层面进行控制系统能够有效地抵御过载和故障提高整体的稳定性。
综合而言网关在微服务架构中扮演了关键角色通过提供统一入口、安全性、路由、负载均衡等功能为整个系统的可维护性、可伸缩性和可用性奠定了基础。
网关的技术实现
在Spring Cloud中实现网关的两种主要方式是使用Zuul和Gateway。下面简要介绍它们的特点和区别
1. Zuul
Zuul是一个基于Servlet的网关实现它在Spring Cloud中充当了路由和过滤器的角色。主要特点包括 阻塞式编程 Zuul采用阻塞式的处理方式即每个请求都会在一个单独的线程中处理等待响应完成后才能继续处理其他请求。 功能全面 Zuul不仅提供了路由功能还支持请求的过滤、认证、授权等多种功能。这使得它成为一个功能较为完备的网关方案。
2. Spring Cloud Gateway
Spring Cloud Gateway是基于 Spring 5 中引入的 WebFlux 框架的响应式编程实现。与 Zuul 相比它具有以下特点 响应式编程 Gateway 采用响应式编程模型利用反应式流处理请求。这使得它能够更高效地处理大量并发请求具备更好的性能。 简化的过滤器链 Gateway 引入了全局过滤器、路由断言和过滤器工厂等概念使过滤器的配置更为灵活。相较于 ZuulGateway 提供了更清晰、简洁的过滤器链定义。 内置断言支持 Gateway 内置了多种路由断言可以根据请求的各种属性进行路由提供了更强大的路由功能。 动态路由 Gateway 支持动态路由配置可以在运行时添加、删除路由规则灵活适应微服务架构的变化。
总体而言选择使用Zuul还是 Spring Cloud Gateway 取决于具体需求和项目的性能要求。Zuul 在功能上较为全面而 Spring Cloud Gateway 则更适用于对性能和响应式编程有较高要求的场景。
一、Gateway 网关的搭建
在理解了为什么需要网关以及网关的作用后我们可以尝试在 cloud-demo 中搭建一个 Gateway 网关。
1.1 创建 Gateway 模块
首先在项目中创建一个新的模块 gateway作为我们的网关服务。 然后为Gateway 模块创建合适的包并创建一个GatewayApplication启动类 SpringBootApplication
public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}
}
1.2 引入依赖
在 pom.xml 文件中引入 Gateway 网关和 Nacos 注册中心的依赖。
!-- 网关依赖 --
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId
/dependency!-- Nacos 服务发现依赖 --
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId
/dependency在上述 pom.xml 文件中你引入了 Spring Cloud Gateway 和 Nacos 服务发现的依赖。这两个依赖的作用 spring-cloud-starter-gateway 这是 Spring Cloud Gateway 的启动器依赖它包含了构建 Gateway 时所需的核心依赖和配置。 spring-cloud-starter-alibaba-nacos-discovery 这是阿里巴巴的 Nacos 服务发现的启动器依赖。它为项目提供了与 Nacos 服务注册和发现相关的功能。
通过这两个依赖就可以在 Spring Cloud 中轻松搭建起一个网关服务并使用 Nacos 作为服务注册与发现的工具。在微服务体系结构中Nacos 的作用是集中管理和发现各个微服务使它们能够相互协作。
1.3 配置网关
在 application.yml 配置文件中编写网关的路由配置和 Nacos 的地址信息。
server:port: 10010 # 网关端口
spring:application:name: gatewaycloud:nacos:server-addr: localhost:8848 # Nacos 地址gateway:routes: # 网关路由配置- id: user-service # 路由 ID自定义的唯一即可# uri: http://127.0.0.1:8081 # 固定的地址uri: lb://userservice # 路由的目标地址其中 lb 代表 loadBalance 负载均衡然后是服务的名称predicates: # 路由断言也就是判断请求是否符合路由规则的条件- Path/user/** # 这个是按照路径匹配只要以/user/开头的请求就符合要求即会路由到 userservice 服务- id: order-serviceuri: lb://orderservicepredicates:- Path/order/**在上述 application.yml 中配置了网关的路由规则和 Nacos 的地址信息。对这个配置文件各个部分的说明 server.port 设置了网关服务的端口为 10010。 spring.application.name 将网关服务的应用名称设置为 gateway。 spring.cloud.nacos.server-addr 配置了 Nacos 注册中心的地址为 localhost:8848。 spring.cloud.gateway.routes 定义了两个网关路由规则。 路由规则1 (user-service) id 路由的唯一标识这里设置为 user-service。uri 设置了路由的目标地址为 lb://userservice其中 lb:// 表示使用负载均衡后面跟着服务的名称 userservice。predicates 路由断言指定了只有请求路径以 /user/ 开头才会匹配到这个路由规则。 路由规则2 (order-service) id 路由的唯一标识这里设置为 order-service。uri 设置了路由的目标地址为 lb://orderservice同样使用了负载均衡后面是服务的名称 orderservice。predicates 路由断言指定了只有请求路径以 /order/ 开头才会匹配到这个路由规则。
这样配置的结果是当请求进入网关时如果路径以 /user/ 开头它将被路由到 userservice 服务如果路径以 /order/ 开头它将被路由到 orderservice 服务。这样通过网关可以在不暴露内部服务地址的情况下统一管理和调度服务。
1.4 验证网关是否搭建成功
通过上述网关的搭建工作之后我们可以启动 gateway 服务然后在浏览器中访问 10010 端口查看是否能够成功访问 userservice 和 orderservice 服务 此时发现分别访问这两个微服务都成功了也就证明了我们的网关也搭建成功了。
1.5 微服务结构分析
通过以上步骤我们创建了一个简单的 Gateway 网关并配置了一个基本的路由规则将请求转发到用户服务。整个 cloud-demo 微服务的结构如下图所示 这个微服务结构图很好地描述了整个系统的架构和流程。以下是对图中各个部分的详细解释 Gateway 网关 网关是整个系统的入口点它接收外部请求并将其路由到不同的微服务。网关的端口为 10010并通过路由规则确定请求的目标微服务。 用户服务 (userservice) 微服务 用户服务处理与用户相关的请求例如用户信息的获取和操作。用户服务通过 Nacos 注册到服务发现中心以便网关可以发现和路由请求到该服务。 订单服务 (orderservice) 微服务 订单服务处理与订单相关的请求例如订单的创建和查询。与用户服务类似订单服务也通过 Nacos 注册到服务发现中心。 Nacos 注册中心 Nacos 提供服务注册和发现功能允许微服务注册并发现其他服务的实例。网关和微服务都通过 Nacos 注册中心来获取服务实例的列表以实现负载均衡和动态路由。 请求流程 用户通过浏览器访问网关的路径例如 http://127.0.0.1:10010/user/1。网关根据路由规则确定将请求路由到 userservice 微服务。网关通过 Nacos 获取 userservice 的服务实例列表。网关选择一个服务实例并使用负载均衡策略将请求转发给该实例。userservice 微服务处理请求并返回结果给网关然后网关将结果返回给用户。
这个微服务结构图清晰地展示了整个系统的工作流程和各个组件之间的关系有助于理解微服务架构的运作方式。通过网关和服务注册中心的协作系统能够实现高可用性、负载均衡和动态扩展以满足不同场景下的需求。
二、Gateway 断言工厂
在上文搭建 Gateway 网关服务的演示中我们提到了路由断言predicates规则而这些规则实际上是由断言工厂Predicate Factory处理的。断言工厂是 Spring Cloud Gateway 提供的一种机制它们负责将配置文件中的字符串规则解析为具体的路由条件。
2.1 Spring 提供的断言工厂
Spring 提供了多种基本的断言工厂每个工厂对应一种路由判断的条件。以下是一些常用的断言工厂及其示例
名称说明示例After请求是否在某个时间点之后。After2037-01-20T17:42:47.789-07:00[America/Denver]Before请求是否在某个时间点之前。Before2031-04-13T15:14:47.43308:00[Asia/Shanghai]Between请求是否在某两个时间点之间。Between2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]Cookie请求是否包含指定的 Cookie。Cookiechocolate, ch.pHeader请求是否包含指定的 Header。HeaderX-Request-Id, \dHost请求是否访问指定的 Host域名。Host**.somehost.org, **.anotherhost.orgMethod请求的方法是否为指定的方式。MethodGET, POSTPath请求的路径是否符合指定规则。Path/red/{segment}, /blue/**Query请求参数是否包含指定参数。Queryname, JackRemoteAddr请求者的 IP 是否在指定范围内。RemoteAddr192.168.1.1/24Weight权重处理通常在负载均衡场景下使用。Weightgroup1, group2
这些断言工厂为网关提供了灵活的路由规则配置使得我们可以根据不同的条件来定制路由策略。在实际使用中可以根据需求组合使用这些断言工厂构建复杂而强大的路由规则。
2.2 示例设置断言工厂
如果我们想要配置某个断言工厂可以直接参考 Spring 的官方文档 例如我们要想设置 After 断言 这个配置中对于 orderservice 使用了两个断言 Path 断言工厂 Path/order/** 表示请求的路径必须以 /order/ 开头才会匹配这个路由规则。 After 断言工厂 After2024-01-01T17:42:47.78908:00[Asia/Shanghai] 表示请求的时间必须在指定的时间点之后即在 2024 年 1 月 1 日 17:42:47上海时区之后。
通过这两个断言路由规则要求请求路径必须以 /order/ 开头并且请求的时间必须在 2024 年 1 月 1 日 17:42:47 之后。只有同时满足这两个条件的请求才会匹配到这个路由规则然后被路由到相应的微服务。
显然当前时间不符合 After 断言工厂如果我们此时尝试访问则会出现 404 错误 那么如果此时将 After 改成 Before 断言工厂呢 显然当前的时间符合要求再次重启并访问便可以成功访问了 通过上述设置断言工厂的例子我们就会发现其实设置某个断言工厂非常简单并且也不需要我们刻意去记某个断言工厂只需要在使用的时候查阅官方文档即可。
三、Gateway 路由过滤器及其工厂
3.1 路由过滤器 GatewayFilter
GatewayFilter 是网关中提供的一种强大的过滤器允许对进入网关的请求和微服务返回的响应进行全面的处理。通过网关过滤器我们可以在请求和响应的不同阶段执行自定义的逻辑例如添加请求头、修改请求体、记录日志、验证权限等。
流程图解释 用户的请求首先经过网关的路由进行转发然后通过一层一层的过滤器链进行过滤。过滤器的作用可以包括查看请求头、修改请求体、记录日志等操作每个过滤器在过滤链中有特定的执行顺序。经过一系列的过滤器处理后请求最终发送给目标微服务。微服务处理完请求后响应的结果同样会经过网关的过滤器链进行处理最终通过路由返回给用户。
通过合理配置和组合不同的网关过滤器我们能够实现灵活、高效的请求处理流程。在实际应用中可以根据具体的业务需求选择合适的过滤器并有选择性地添加、移除或自定义过滤器以实现定制化的网关处理逻辑。
3.2 路由过滤器工厂 GatewayFilter Factory
Spring 提供了三十多种不同的路由过滤器工厂通过 Spring 官网文档 可以查询这些过滤器工厂具体的使用方法 这些过滤器工厂包括但不限于 AddRequestHeader GatewayFilterFactory 为请求添加头信息。 filters:- AddRequestHeaderHeaderName, HeaderValueAddResponseHeader GatewayFilterFactory 为响应添加头信息。 filters:- AddResponseHeaderHeaderName, HeaderValueRewritePath GatewayFilterFactory 重写请求路径。 filters:- RewritePath/foo/(?segment.*), /$\{segment}SetPath GatewayFilterFactory 设置请求路径。 filters:- SetPath/fooRequestRateLimiter GatewayFilterFactory 请求速率限制。 filters:- RequestRateLimiterRateLimitKey, replenishRate, burstCapacity以上是一些常用的过滤器工厂通过合理配置这些过滤器工厂我们可以实现对请求和响应的灵活处理。在实际应用中可以根据具体的需求选择相应的过滤器工厂并按需组合使用以实现定制化的网关处理逻辑。
3.3 示例添加过滤器工厂
在这个示例中我们可以给所有进入 userservice 服务的请求添加一个请求头HelloHello GatewayFilterFactory!注意实际上这是一个键值对。
具体的操作则是在gateway服务中修改application.yml文件给userservice的路由添加过滤器
验证是否添加请求头成功的方式则可以在 userservice 的请求用户信息方法中新增一个参数例如
GetMapping(/{id})
public User queryById(PathVariable(id) Long id, RequestHeader(value Hello, required false) String hello) {System.out.println(Hello: hello);return userService.queryById(id);
}在这个 Controller 方法中新增了一个 hello 参数其来源是 HTTP 的请求头使用 RequestHeader 注解标注并且使用 required 指定了这个参数不是必传的然后重启 userservice 并在浏览器中进行访问在控制台上成功打印了“Hello: Hello GatewayFilterFactory!” 日志 3.4 默认过滤器
通过上面的示例我们知道了如何给某个微服务的请求加上过滤器但是如果要给所有服务的请求都加上过滤器该如何操作呢
可能我们首先会想到分别给各个微服务都加上过滤器的配置项但是这样就显得非常冗余了。此外我们还可以使用默认过滤器default-filters的方式来给所有的微服务请求都加上相同的过滤器配置例如 此时我们可以尝试把 userservice 中的过滤器配置给注释掉然后再次重启服务并访问看看默认过滤器配置是否生效。 此时便说明我们的默认过滤器配置生效了。
四、Gateway 全局过滤器
在前文中我们已经了解了请求路由的过滤器工厂以及默认过滤器 default-filters 的作用。现在让我们深入研究另一个强大的概念——全局过滤器 GlobalFilter。
4.1 全局过滤器的概念和作用
1. 概念
全局过滤器是 Spring Cloud Gateway 中的一种过滤器类型它的作用是处理所有进入网关的请求和从微服务返回的响应。与局部过滤器GatewayFilter不同全局过滤器的逻辑需要通过代码来实现而不是通过配置来定义。
全局过滤器是在整个请求-响应周期中起作用的过滤器。它可以执行一些全局性的任务如认证、授权、日志记录、性能监控等。全局过滤器不仅可以处理请求还可以处理从微服务返回的响应使其成为一个更为强大和灵活的过滤器类型。
2. 作用 统一处理全局任务 全局过滤器可以用于执行与整个微服务架构相关的任务而不仅仅是单个路由或微服务的请求处理。这使得它非常适合于执行全局性的操作例如在每个请求中执行身份验证、记录请求日志等。 修改请求和响应 通过全局过滤器可以在请求到达微服务之前或响应返回客户端之前修改请求或响应。这种能力对于实施诸如请求重写、响应重写、添加头信息等操作非常有用。 集成外部服务 全局过滤器还可以用于集成外部服务例如在请求中调用身份验证服务或其他微服务以获取必要的信息或执行某些任务。
4.2 GlobalFilter 接口定义
public interface GlobalFilter { /*** 处理当前请求有必要的话通过 {link GatewayFilterChain} 将请求交给下一个过滤器处理** param exchange 请求上下文里面可以获取 Request、Response 等信息 * param chain 用来把请求委托给下一个过滤器 * return {code MonoVoid} 返回标识当前过滤器业务结束*/MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain);
}上述代码展示了 GlobalFilter 接口的定义。其中关键部分的说明如下 filter: 这是 GlobalFilter 接口的核心方法负责处理当前请求。参数 ServerWebExchange 提供了请求上下文其中包含了请求和响应的相关信息。参数 GatewayFilterChain 则用于将请求委托给下一个过滤器处理。 返回类型 MonoVoid 表示当前过滤器的业务逻辑是否已经处理完毕。如果返回的 Mono 完成了那么表示当前过滤器的任务已完成请求将继续传递给下一个过滤器。如果 Mono 未完成请求将被阻塞。
4.3 示例定义全局过滤器进行用户身份验证
在微服务架构中用户身份验证是保护服务安全的重要一环。通过定义全局过滤器我们可以在请求进入网关时对用户身份进行验证以确保只有合法用户才能访问服务。本示例将展示如何使用 Spring Cloud Gateway 实现一个简单的用户身份验证全局过滤器。 1. 需求说明 我们的需求是拦截请求判断请求参数中是否包含 authorization 参数且其值是否为 “admin”。如果满足条件请求将被放行否则请求将被拦截。 2. 实现过程 首先我们创建一个全局过滤器 AuthorizeFilter并实现 GlobalFilter 接口
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerHttpRequest;
import org.springframework.util.MultiValueMap;
import reactor.core.publisher.Mono;Component
public class AuthorizeFilter implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1. 获取请求参数ServerHttpRequest request exchange.getRequest();MultiValueMapString, String params request.getQueryParams();// 2. 获取参数中的 authorization 参数String authorization params.getFirst(authorization);// 3. 判断参数值是否等于 adminif(admin.equals(authorization)){// 4. 等于则放行相当于调用过滤器链中的下一个过滤器return chain.filter(exchange);}// 5. 不等于则拦截// 5.1 设置状态码exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);// 5.2 拦截请求return exchange.getResponse().setComplete();}Overridepublic int getOrder() {return -1;}
}在这个过滤器中我们获取请求参数中的 authorization 参数并判断其值是否为 “admin”。如果是请求将继续传递给过滤器链中的下一个过滤器否则设置响应状态码为 UNAUTHORIZED表示请求未被授权并终止请求处理。 3. 过滤器执行顺序 过滤器的执行顺序可以通过 Order 注解的方式实现另外也可以通过实现 Ordered 接口并重写其中的 getOrder 方法。在上述代码中通过实现 Ordered 接口我们可以指定过滤器的执行顺序。在这个例子中通过 getOrder 方法返回 -1表示这个过滤器的执行顺序较高会在一般过滤器之前执行。 4. 验证全局过滤器是否生效 重启 gateway 服务首先直接访问userservice 不带任何参数 发现访问失败并且响应码为 401。
加上 authorization 参数再进行访问 此时便可以成功访问了当然如果 authorization 参数的值不为 admin 也会访问失败 通过定义这个简单的全局过滤器我们实现了对用户身份的基本验证。在实际应用中用户身份验证通常会更为复杂可能涉及调用认证服务、检查 token 签名等操作。这个示例提供了一个基本的框架可以根据实际需求进行扩展确保微服务的安全性和可靠性。
五、过滤器链的执行顺序
在 Spring Cloud Gateway 中过滤器链的执行顺序是确保请求经过一系列过滤器并按照特定的规则执行的关键。一般而言请求进入网关后会遇到三类过滤器当前路由的过滤器、DefaultFilter、GlobalFilter。
5.1 过滤器链执行过程
请求路由后当前路由过滤器、DefaultFilter、GlobalFilter 会被合并到一个过滤器链集合中并按照排序规则进行排序然后按照排序后的顺序依次执行。这个过程如下图所示 5.2 过滤器的排序规则
为了确保过滤器按照正确的顺序执行遵循以下排序规则 自定义过滤器 每个自定义过滤器必须指定一个整数类型的 order 值数值越小优先级越高执行顺序越靠前。 GlobalFilter 全局过滤器通过实现 Ordered 接口或添加 Order 注解来指定 order 值由开发者自行指定。值越小优先级越高。 路由过滤器和 DefaultFilter 路由过滤器和 DefaultFilter 的 order 由 Spring 框架指定默认按照声明顺序从1递增。 相同 order 值处理 当过滤器的 order 值相同时执行顺序为 DefaultFilter 路由过滤器 GlobalFilter。具体实现可以查看一些关键类的源码如 org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters() 和 org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()。
过滤器链的执行顺序非常关键它保证了过滤器能够按照开发者期望的顺序执行。通过合并路由过滤器、DefaultFilter 和 GlobalFilter并按照指定的执行顺序排序网关可以对请求进行精细控制实现各种定制化的业务逻辑。在实际开发中了解和正确使用过滤器链的执行规则是确保网关正常工作的基础。
5.3 为什么三种不同的过滤器可以进行排序形成过滤器链
首先对于路由过滤器和默认过滤器中的AddRequestHeader过滤器工厂来说它们的底层都是由AddRequestHeaderGatewayFilterFactory 类实现的。
通过查看 AddRequestHeaderGatewayFilterFactory 类的源码可以知道它们最后最后转化成一个相同类型的对象即GatewayFilter 但是对于 GlobalFilter 和 GatewayFilter 这两个接口来说查看它们的源码并没有发现继承关系 那么是否就意味着它们之间没有关系了呢其实不然在 FilteringWebHandler 这个类中有一个静态内部类GatewayFilterAdapter 可以发现这个类实现了GatewayFilter接口并且其中有一个属性其类型是GlobalFilter。可以发现可以类的作用是把GlobalFilter适配成了GatewayFilter。
因此这三种过滤器最终都可以当成GatewayFilter所有它们之间可以按照Ordered接口、Order注解、默认等指定的顺序放在同一个过滤器链中。
六、跨域问题
6.1 什么是跨越问题
跨域问题是指在 web 应用程序中由于安全策略的限制浏览器禁止在一个源origin的网页应用程序中发起对另一个源的 HTTP 请求。这个源包括协议、域名、端口的组合只有当两个请求的源相同时浏览器才允许跨域请求。
跨域问题主要由以下情况引起 不同域名 当两个请求的域名不同即使协议和端口相同也会被认为跨域。例如www.example.com 和 api.example.com。 不同端口 即使在同一个域名下如果请求的端口不同也会被认为跨域。例如example.com:8080 和 example.com:3000。 不同协议 当一个请求使用 HTTP 协议而另一个使用 HTTPS 协议时也会被视为跨域。
跨域问题的存在是为了增加 web 安全性防止恶意网站利用用户的浏览器向其他网站发起恶意请求窃取用户信息等。
解决跨域问题的常见方式之一是使用 CORS跨域资源共享策略它允许服务器在响应中附加一些标头告诉浏览器哪些域名允许跨域访问资源。当浏览器发起跨域请求时会先发送一个预检请求OPTIONS 请求给服务器服务器根据预检请求的信息来判断是否允许跨域访问。如果服务器返回合适的响应头浏览器才会允许跨域请求。这种方式可以有效地解决跨域问题同时保障了网站的安全性。
6.2 演示跨越问题
为了演示跨域问题我们首先创建一个简单的 HTML 文件 index.html其中包含了一个使用 Axios 发起的 AJAX 请求
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0meta http-equivX-UA-Compatible contentieedgetitleDocument/title
/head
body
pre
spring:cloud:gateway:globalcors: # 全局的跨域处理add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题corsConfigurations:[/**]:allowedOrigins: # 允许哪些网站的跨域请求- http://localhost:5500allowedMethods: # 允许的跨域ajax的请求方式- GET- POST- DELETE- PUT- OPTIONSallowedHeaders: * # 允许在请求中携带的头信息allowCredentials: true # 是否允许携带cookiemaxAge: 360000 # 这次跨域检测的有效期
/pre
/body
script srchttps://unpkg.com/axios/dist/axios.min.js/script
scriptaxios.get(http://localhost:10010/user/1?authorizationadmin).then(resp console.log(resp.data)).catch(err console.log(err))
/script
/html说明
此时我们假设 http://localhost:10010/user/1 是一个需要进行跨域访问的服务。然后使用 VS Code 中的 Live Server 插件启动 index.html然后通过浏览器的开发者工具查看控制台的输出内容 发现出现了跨越问题导致不能正常访问userservice的服务。
6.3 使用 Gateway 解决跨域问题
6.3 使用 Gateway 解决跨域问题
为了解决跨域问题我们可以在 gateway 服务的 application.yml 中新增如下的配置使用 Spring Cloud Gateway 的跨域配置
spring:cloud:gateway:globalcors: # 全局的跨域处理add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题corsConfigurations:[/**]:allowedOrigins: # 允许哪些网站的跨域请求- http://localhost:5500allowedMethods: # 允许的跨域 ajax 的请求方式- GET- POST- DELETE- PUT- OPTIONSallowedHeaders: * # 允许在请求中携带的头信息allowCredentials: true # 是否允许携带 cookiemaxAge: 360000 # 这次跨域检测的有效期说明
allowedOrigins允许跨域请求的源这里设置为 http://localhost:5500。allowedMethods允许的跨域 AJAX 请求方式包括 GET、POST、DELETE、PUT、OPTIONS。allowedHeaders允许在请求中携带的头信息设置为 * 表示允许所有头信息。allowCredentials是否允许携带 Cookie。maxAge这次跨域检测的有效期设置为 360000 毫秒。
通过这样的配置我们告诉 Spring Cloud Gateway 允许指定的源http://localhost:5500发起跨域请求并指定了其他的一些跨域配置。
然后重新访问 localhost:5500发现控制台成功输出了访问userservice 的结果了