使用SpringCloudApiGateway之支持Cors跨域请求
使用SpringCloudApiGateway之支持Cors跨域请求,恰卡网带你了解更多相关信息。
问题背景
公司的项目需要前后端分离,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://www.zzm8.com/d/file/p/20210716150015133567/20210716150015133568" 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 方法和添加允许源来解决。希望能给大家一个参考,也希望大家多多支持趣讯吧
推荐阅读
-
洗衣机不脱水了是怎么回事(洗衣机不甩干的处理方法)
洗衣机作为大家日常生活必备的家用电器,其利用率频繁,难免会因为机械磨损、缺乏润滑油、机件老化、弹簧疲劳变形等原因,出现各种不正...
-
电子表格零基础自学教程(小白也能学明白)
可能很多人(包括我)觉得Excel不就是做个表吗,没什么好学的。然而很多大型企业在面试的时候还是会问,“会Excel吗?”“会...
-
笔记本电脑报价大全(联想笔记本多少钱)
(注意:建议在旗舰店、官方旗舰店、官网购买) 一、游戏本设计本、办公本推荐如下: 华为品牌:(全球第一大电信设备商) 1...
-
煲机软件哪个好(让耳机有个思想准备)
《无间道》中陈永仁与刘建明有过一句经典对白——“高音甜、中音准、低音沉,总之一个词通透”。这一句话也一...
-
viewsonic平板电脑(viewsonic平板电脑刷机)
ViewSonic是一个视讯品牌,中文名字:优派。 ViewSonic 一、读音:英[vju:][?s?n?k],美[vj...
-
采访麦克风户外哪款好(讯飞智能无线麦克风C1采访神器)
对于视频创作者、直播工作者、远程培训老师、记者等媒体工作者来说,工作过程中,最让人费心的莫过于如何确保收音纯正、字幕快速生成、...
-
电脑硬件配置怎么查(详述两招快速查看电脑配置参数信息)
大家好,今天跟大家分享两个快速查看电脑配置参数信息的办法。 操作步骤如下: 1右击电脑屏幕最下方任务栏左侧的电脑徽标按钮,...
-
数据线没坏但充不上电怎么办(数据线充不上电处理方法)
苹果充电器突然充不上电是比较尴尬的问题,首先看自己的充电器数据线是不是原装,如果非原装在第一次充电时,苹果手机会提示你是否要适...
-
电脑开机出现黑屏如何处理(电脑不能开机黑屏解决方法)
电脑不能开机或者开机以后黑屏怎么解决?这里收集了所有常见的维修方法,看完秒变维修高手,实在是一篇不能错过的电脑维修教程。简单易...
-
手机宝典怎么搞(小米手机性能优化宝典)
别再总是抱怨手机卡顿,系统臃肿,反应慢,现在看完这篇文章,你会发现你并不了解小米手机,当然,文中许多方法并不是仅仅适用于小米手...