使用SpringCloudApiGateway之支持Cors跨域请求
作者:Moshow郑锴 发布时间:2022-10-15 18:28:08
问题背景
公司的项目需要前后端分离,vue+java,这时候就需要支持Cors跨域请求了。最近对zuul进行升级,假如说zuul是1.0的话,api gateway就是2.0的网关,支持ws等,基于NIO,各方面还是强大的。
解决方案
新建一个Configuration类即可
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
/**
* SpringApiGateway Cors
*/
@Configuration
public class RouteConfiguration {
//这里为支持的请求头,如果有自定义的header字段请自己添加(不知道为什么不能使用*)
private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client";
private static final String ALLOWED_METHODS = "*";
private static final String ALLOWED_ORIGIN = "*";
private static final String ALLOWED_Expose = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client";
private static final String MAX_AGE = "18000L";
@Bean
public WebFilter corsFilter() {
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
if (CorsUtils.isCorsRequest(request)) {
ServerHttpResponse response = ctx.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
headers.add("Access-Control-Expose-Headers", ALLOWED_Expose);
headers.add("Access-Control-Allow-Credentials", "true");
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
/**
*
*如果使用了注册中心(如:Eureka),进行控制则需要增加如下配置
*/
@Bean
public RouteDefinitionLocator discoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient) {
return new DiscoveryClientRouteDefinitionLocator(discoveryClient);
}
}
application.yml配置
官方文档提及到还有另外一种方式,就是通过yml来配置。
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "https://blog.csdn.net/moshowgame"
allowedMethods:
- GET
跨域解决方案(CORS)
1. 什么是跨域?
跨域问题是出于浏览器的【同源策略】限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。
可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。
所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
由于我们现在是采用的前后端分离的微服务架构,前端和后端必定存在跨域问题。解决跨域问题可以采用CORS。
2. CORS简介
CORS 是一个 W3C 标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
CORS需要浏览器和服务器同时支持。但是目前基本上浏览器都支持,所以我们只要保证服务器端服务器实现了 CORS 接口,就可以跨源通信。
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
3. 具体解决方式
解决跨域问题,就是在服务器端给响应添加头信息
Name | Required | Comments |
---|---|---|
Access-Control-Allow-Origin | 必填 | 允许请求的域 |
Access-Control-Allow-Methods | 必填 | 允许请求的方法 |
Access-Control-Allow-Headers | 可选 | 预检请求后,告知发送请求需要有的头部 |
Access-Control-Allow-Credentials | 可选 | 表示是否允许发送cookie,默认false; |
Access-Control-Max-Age | 可选 | 本次预检的有效期,单位:秒; |
3.1 在Spring Boot 中解决
在spring boot中给我们提供了 @CrossOrigin 注解用于解决跨域问题。
使用场景要求:jdk1.8+、Spring4.2+
只需要在我们需要的controller上加@CrossOrigin
@RestController
//实现跨域注解
//origin="*"代表所有域名都可访问
//maxAge飞行前响应的缓存持续时间的最大年龄,简单来说就是Cookie的有效期 单位为秒若maxAge是负数,则代表为临时Cookie,不会被持久化,Cookie信息保存在浏览器内存中,浏览器关闭Cookie就消失
@CrossOrigin(origins = "*",maxAge = 3600)
@RequestMapping("/album")
public class AlbumController {}
3.2 在spring Cloud中解决
只需要在spring Cloud Gateway 服务中添加配置就行
spring:
application:
name: system-gateway
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]': # 匹配所有请求
allowedOrigins: "*" #跨域处理 允许所有的域
allowedMethods: # 支持的方法
- GET
- POST
- PUT
- DELETE
当然也可以自己利用Gateway的 * 来手动添加相应的头信息
default-filters:
- AddResponseHeader=Access-Control-Allow-Credentials,true
- AddResponseHeader=Access-Control-Allow-Headers,access-control-allow-origin
- AddResponseHeader=Access-Control-Allow-Methods,GET
- AddResponseHeader=Access-Control-Allow-Origin,*
- AddResponseHeader=Access-Control-Allow-Age,3600
3.3 在Nginx中解决
location /example {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Max-Age 1728000;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header Content-Type' 'text/plain; charset=utf-8';
add_header Content-Length 0 ;
return 204;
}
+ if ($http_origin ~* (https?://(.+\.)?(example\.com$))) {
+ add_header Access-Control-Allow-Origin $http_origin;
+ add_header Access-Control-Allow-Credentials true;
+ add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
+ add_header Access-Control-Expose-Headers Content-Length,Content-Range;
+ }
proxy_redirect off;
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_pass http://127.0.0.1:8080/;
}
解释:
if ($request_method = 'OPTIONS') {...} 当请求方法为 OPTIONS 时:
添加允许源 Access-Control-Allow-Origin 为 * (可根据业务需要更改)
添加缓存时长 Access-Control-Max-Age,当下次请求时,无需再发送 OPTIONS 请求
添加允许的方法,允许的首部
添加一个内容长度为0,类型为 text/plain; charset=utf-8 , 返回状态码为 204 的首部
if ($http_origin ~* (https?://(.+\.)?(example\.com$))) {...}, 当 origin 为合法域名(可根据业务调整或去除合法域名验证)时:
添加允许源Access-Control-Allow-Origin为 $http_origin (可根据业务需要更改)
添加允许认证Access-Control-Allow-Credentials为 true ,允许接收客户端 Cookie(可根据业务需要更改。 但要注意,当设置为true时,Access-Control-Allow-Origin 不允许设置为 *)
添加允许的方法,暴露的首部
至此,完成跨域请求正确响应。
以上,是对跨域请求在Web Server的解决方案,主要是通过响应 OPTIONS 方法和添加允许源来解决。希望能给大家一个参考,也希望大家多多支持脚本之家
来源:https://zhengkai.blog.csdn.net/article/details/84618781


猜你喜欢
- synchronized 和 Reentrantlock多线程编程中,当代码需要同步时我们会用到锁。Java为我们提供了内置锁(synchr
- 前言Spring 提供了 ApplicationContext 事件机制,可以发布和监听事件,这个特性非常有用。Spring 内置了一些事件
- 项目结构:运行效果:========================================================下面是代
- 周末这天手痒,正好没事干,想着写一个分页的例子出来给大家分享一下。这个案例分前端和后台两部分,前端使用面向对象的方式写的,里面用到了一些回调
- 新建Rest服务接口:[ServiceContract]public interface IService1{ &nb
- Java内存区域与内存溢出异常概述对于 C 和 C++程序开发的开发人员来说,在内存管理领域,程序员对内存拥有绝对的使用权,但是也要主要到正
- XML中的扫描过程<?xml version="1.0" encoding="utf-8" ?
- java身份证合法性校验并获取身份证号有效信息,供大家参考,具体内容如下java身份证合法性校验/**身份证前6位【ABCDEF】为行政区划
- Android平台是建立在Linux基础上,以Java语言为主的一个操作系统平台。它的开发涉及到很多方面,但其实并不复杂,上面的路线图看似需
- 一、实验目的1. 掌握输入输出流的总体结构;2. 掌握流的概念;3. 掌握FileInputStream类、FileOutputStream
- 前几天开发公司项目,有个地方要做一个分数的仪表盘,根据分数跑分,(设计的人估计是看到招商银行App的账号总览)网上好像找不到类似的组件,那就
- 一、项目需求二、项目思路1、菜单制作2、中奖号码生成 getNumber (随机数 Math.random)3、购买号码和中奖号码比对 生成
- JavaFx初探一,UI控件的使用,具体内容如下方式一:使用纯代码直接new view控件,这样就不涉及到与fxml文件之间的交互了方式二:
- 背景近期因实际项目需要,在特定操作下触发定位请求,取到用户位置及附近位置。问题:经初步选型,最终决定接入百度定位,按照百度定位SDK And
- 目录MVC结构简介SpringMVC简介SpringMVC执行流程常用注解1. @Controller2. @ResponseBody3.
- AspectJ简介它不属于spring;AspectJ是一个AOP的框架;定义了AOP语法;有一个专门的编译器用来生成遵守Java字节编码规
- 普通商户分账功能分账比例:目前只有”低比例分账“小于等于30%分账,分账金额需要减去(千6)手续费.每一张订单只能分发,当前订单总额的百分之
- java抠图片文字或签名运行原理第一步 遍历像素点BufferedImage image = ImageIO.read(new File(i
- 背景在开发中,如果用try catch的方式,每个方法都需要单独实现,为了方便分类异常,返回给前端,采用了@ControllerAdvice
- 本文实例讲述了C#调用SQLite的方法。分享给大家供大家参考。具体分析如下:一、SQLite简介:当我们用到海量数据时一般会用Oracle