谷粒商城实战笔记-47-商品服务-API-三级分类-网关统一配置跨域

一,跨域问题

当上一节设置好通过网关转发请求后,点击登录按钮,无法登录。

浏览器控制台有报错信息,如下。

在这里插入图片描述

图上的信息表明出现了跨域问题

跨域问题是Web开发中常见的问题,尤其在前后端分离的架构中更为突出。

以“谷粒商城”为例,前端应用和后端服务部署分开部署,端口号不同。当前端应用尝试从后端API请求数据时,就会遇到跨域问题。

1,跨域问题产生的原因

浏览器出于安全考虑,实施了同源策略(Same-Origin Policy)。

根据同源策略,来自不同源(协议、域名、端口任意一项不同即视为不同源)的HTTP请求被限制,不能相互读取或写入对方的资源。

一定要协议、域名或者IP、端口都一致时,才不会被同源策略限制,可参考下面列表。

在这里插入图片描述

上面的例子中,首先访问前端项目,端口是8001,打开登录界面后,点击登录,登录接口会发给网关,网关的端口是80,根据同源策略,端口不同不允许访问,会被浏览器限制访问。

2,预检请求

在这里插入图片描述

上面图片中的OPTIONS,说明这个请求是个预检请求。

为什么需要预检请求呢?

原因是同源策略是浏览器的安全策略,在不同源的情况下,服务器端如果允许跨域的话,浏览器仍然可以发出跨域请求。

如果不同源,浏览器先发送一个轻量级的预检请求,询问服务器是否允许跨域访问,如果允许跨域访问,才会真正的发出请求。

在这里插入图片描述

上图图描述了非简单请求(如PUT、DELETE等)的跨域过程,具体来说,这是一个典型的CORS(Cross-Origin Resource Sharing)预检请求的过程。下面是详细的解释:

  1. 预检请求,OPTIONS
    浏览器发送一个预检请求(OPTIONS),询问服务器是否允许跨域请求。这个请求带有特殊的HTTP头,比如Origin表示请求来源的URL,以及Access-Control-Request-Method表示实际请求将使用的HTTP方法。

  2. 响应允许跨域
    服务器收到预检请求后,检查请求头,如果满足条件(如允许的源、方法、请求头等),则返回一个成功的响应,包含Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers等头,表明允许跨域请求。如果服务器不允许跨域,则返回一个失败的响应。

  3. 发送真实请求
    如果预检请求得到允许,浏览器才会发送真实的HTTP请求(如PUT或DELETE),携带实际的数据。

  4. 响应数据
    服务器处理完请求后,返回响应数据。此时,响应头中应包含Access-Control-Allow-Origin等头,确认允许跨域。

这个过程是为了保护用户的安全,防止恶意网站窃取敏感数据。只有在预检请求得到允许后,浏览器才会发送真正的请求。对于简单请求(如GET、POST),浏览器可以直接发送,不需要预检请求。但对于非简单请求,浏览器必须先验证服务器是否允许跨域,以确保用户的隐私和安全。

3,跨域解决方案

只要浏览器允许跨域,浏览器就可以发出跨域请求。

解决跨域问题的常见方法有以下几种:

3.1 CORS (Cross-Origin Resource Sharing)

CORS 是一种最常用的跨域解决方案,允许服务器通过响应头来指定哪些源可以访问其资源。

服务器需要在响应中添加Access-Control-Allow-Origin头来指明哪些源可以访问资源。

此外,还可以设置Access-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Allow-Credentials等头来细化跨域访问的控制。

后端配置示例(Spring Boot)
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*") // 或指定的源
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*")
                .allowCredentials(false)
                .maxAge(3600);
    }
}

3.2 JSONP (JSON with Padding)

JSONP是一种用于绕过同源策略的技巧,但它仅限于GET请求。前端向服务器发送一个GET请求,服务器将数据包裹在回调函数中返回。这种方式的安全性较低,且不支持POST等其他HTTP方法。

3.3 代理服务器

通过设置一个代理服务器(如Nginx或Node.js的Express应用),前端向代理服务器发送请求,代理服务器再向实际的后端API发送请求。这样前端和后端看似在同一源下通信,绕过了同源策略的限制。

Nginx代理配置示例
location /api/ {
    proxy_pass http://backend_server;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

3.4 Server-Side Proxy (后端代理)

在后端API中添加逻辑,将请求转发到另一个源。这通常用于微服务架构中,一个服务充当其他服务的代理。

3.5 使用WebSocket

WebSocket协议不受同源策略的限制,可以用于建立持久的双向通信通道,适用于实时数据传输场景。

3.6 PostMessage API

HTML5引入的postMessageAPI允许不同源的窗口之间进行安全通信,通常用于iframe之间的通信。

3.7 CORS Anywhere

CORS Anywhere是一个开源的Node.js中间件,可以作为代理服务器,自动添加CORS响应头,使得任何源都可以访问资源。但它可能涉及安全和隐私问题,应当谨慎使用。

我们采用第一种方案。

二,解决方案

考虑到所有的请求都会经过网关,所以可以在网关设置允许跨域,这样就不需要在每一个服务都进行跨域配置了。

我们通过创建一个配置类,在配置类中创建一个过滤器,过滤器给经过的所有请求的请求头加上允许跨域的信息。

在这里插入图片描述

配置类代码如下。

package com.atguigu.gulimall.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@Configuration
public class GulimallCorsConfiguration {

    @Bean
    public CorsWebFilter corsWebFilter(){
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration();

        //1、配置跨域
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOriginPattern("*");
        corsConfiguration.setAllowCredentials(true);

        source.registerCorsConfiguration("/**",corsConfiguration);
        return new CorsWebFilter(source);
    }
}

经过这样设置之后,再次操作,就顺利登录了。

  • 15
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Spring Cloud网关跨域配置可以通过以下步骤来完成。 首先,在Spring Cloud网关项目的配置文件中进行相关配置。可以通过在配置文件中设置以下属性来允许跨域访问: ```yml spring: cloud: gateway: globalcors: corsConfigurations: '[/**]': allowedOrigins: "*" allowedMethods: - GET - POST allowCredentials: true ``` 上述配置中,allowedOrigins设置为"*"表示允许来自所有域的请求。 其次,可以在编写路由规则的时候,设置cors参数来针对特定的请求路径进行跨域配置。例如: ```yml spring: cloud: gateway: routes: - id: service-route uri: http://localhost:8081 predicates: - Path=/service/** filters: - RewritePath=/service/(?<remaining>.*), /\$\{remaining} - RewritePath=/service/(?<remaining>.*), /\$\{remaining} metadata: response-headers: Access-Control-Allow-Origin: "*" Access-Control-Allow-Methods: "GET, POST" Access-Control-Max-Age: "3600" Access-Control-Allow-Headers: "Content-Type, x-requested-with, Authorization" ``` 在上述示例中,针对路径为/service/**的请求进行了跨域配置,允许来自任意域的请求,并设置了允许的请求方法和响应头信息。 最后,还可以使用自定义的CorsWebFilter来进行更灵活的跨域配置。可以通过编写一个实现CorsConfigurationSource接口的类,并在该类中自定义cors配置,然后在WebFluxConfigurer中注册该CorsConfigurationSource实现即可。 通过以上的配置和步骤,Spring Cloud网关可以实现跨域访问的配置。这样就能够允许不同域的请求访问网关,并实现前后端的数据交互。 ### 回答2: Spring Cloud Gateway 是基于Spring WebFlux框架的一个API网关服务,用于构建微服务架构中的路由转发和过滤器链。在Spring Cloud Gateway中配置跨域请求是相对较简单的。 在Spring Cloud Gateway中可以通过添加过滤器来实现跨域请求。首先,在配置文件中添加路由配置,指定需要跨域的路径和目标服务。然后,编写一个全局的过滤器类,通过继承GlobalFilter和Ordered接口来实现全局过滤器。在过滤器中,通过CorsUtils类来判断请求是否为跨域请求,如果是,则设置跨域响应头信息。 具体的步骤如下: 1. 在application.yml文件中配置路由: ```yaml spring: cloud: gateway: routes: - id: myRoute uri: http://example.com predicates: - Path=/api/** filters: - StripPrefix=1 ``` 2. 创建一个全局的过滤器类CorsFilter.java: ```java @Component public class CorsFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); if (CorsUtils.isCorsRequest(request)) { ServerHttpResponse response = exchange.getResponse(); HttpHeaders headers = response.getHeaders(); headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*"); headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, PUT, OPTIONS, DELETE"); headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*"); headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600"); headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*"); headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); } return chain.filter(exchange); } @Override public int getOrder() { return -1; } } ``` 3. 启动应用,并访问配置跨域接口。 通过以上步骤,我们可以简单地在Spring Cloud Gateway中配置跨域请求。在过滤器中,我们判断请求是否为跨域请求,并在响应头中添加相关的跨域信息。这样,就能够实现对跨域请求的支持。 ### 回答3: Spring Cloud网关是一个基于Spring Cloud的微服务架构中的核心组件,它可以用来进行统一的请求路由、请求过滤、集中认证等功能。当我们在使用Spring Cloud网关时,可能会遇到跨域的问题,下面我将详细介绍Spring Cloud网关跨域配置。 要配置Spring Cloud网关跨域,我们可以在网关配置文件中添加如下代码段: ``` spring: cloud: gateway: globalcors: cors-configurations: '[/**]': allowed-origins: '*' allowed-methods: - GET - POST - PUT - DELETE allowed-headers: '*' allow-credentials: true max-age: 1800 ``` 在这个配置中,我们使用`spring.cloud.gateway.globalcors.cors-configurations`参数指定了全局的CORS配置。`'[/**]'`表示匹配所有路径,我们也可以根据自己的需求指定一个具体的路径。`allowed-origins`指定了允许的源,可以使用`*`表示允许所有源。`allowed-methods`指定了允许的HTTP方法。`allowed-headers`指定了允许的自定义头信息。`allow-credentials`表示是否允许发送cookie等身份验证信息。`max-age`表示预检请求的缓存时间。 除了全局配置外,我们还可以在GatewayFilter中对特定的路径进行跨域配置,例如: ``` @Configuration public class GatewayConfig { @Bean public RouteLocator routeLocator(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r.path("/api/**") .filters(f -> f.hystrix(c -> c.setFallbackUri("/fallback"))) .uri("lb://service-a")) .build(); } @Bean public CorsWebFilter corsFilter() { return new CorsWebFilter(new UrlBasedCorsConfigurationSource()); } } ``` 在上述配置中,`routeLocator()`方法用于配置路由规则,其中`.path("/api/**")`表示匹配以`/api/`开头的路径,然后使用`filters()`方法添加一些过滤器,最后使用`uri()`方法将请求转发到service-a服务。 `corsFilter()`方法用于添加CorsWebFilter,通过`UrlBasedCorsConfigurationSource`来实现对特定路径的跨域配置。 以上就是Spring Cloud网关跨域配置的一些常用方法,我们可以根据实际需求选择适合的方式来配置跨域

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小手追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值