Skip to main content

CORS跨域配置

1 什么是跨域?

跨域是指浏览器上在原有已经打开了的页面上再另外去了请求新的数据,而这个另外新的请求如果满足跨域条件,而服务端没有允许这样的请求行为的话,浏览器会直接 中断这个请求。那什么什么样的请求算是跨域请求呢?满足以下任一条件就是跨域请求:

URL说明
已打开的链接: http:domain1.com
要请求的链接: http:domain1.com:8080
跨域了, 端口不一样
已打开的链接: http:domain1.com
要请求的链接: https:domain1.com
跨域了, 协议不一样
已打开的链接: http:domain1.com
要请求的链接: http:domain2.com
跨域了, 域名不一样

总结就一名句话,同源同端口同协议,不算跨域,否则就是了。
如果满足跨域条件了,通常浏览器会先发送个Option请求,去试探服务器是不是允许当前这个跨域请求,浏览器发出OPTION试探请求时会把要求写在请求头部上,浏览器和服务器的对话大概如下:

浏览器的OPTION请求头
access-control-request-headers: content-type // <-- 浏览器将要发出去的请求有content-type这一请求头部字段
access-control-request-method: POST // <-- 浏览器将要发出去的请求是POST方式
origin: http://domain.com // <-- 浏览器将要发出去的请求是基于已经打开该域名的页面之上
...

然后服务器那边就给出了回应,回答都写在响应头部中,内容如下:

服务器响应了浏览器的OPTION请求,这是响应内容
access-control-allow-headers: content-type // <-- 服务器接受content-type头部字段
access-control-allow-methods: POST // <-- 服务器接受 POST 请求
access-control-allow-origin: * // <-- 服务器接受 任意的域名
...

然后浏览器拿这一请求信息和响应信息一对比,来确定预备中的请求是否满足条件,如果是则直接发送,如果不满足条件则中断预备中的请求。
那么这么做的目的是什么?为什么?我想有1个好处:

  • 1 防止CORS攻击服务器的流量。如果没有这一浏览器的策略拦截,那么,会被人恶意使用,造成可能不必要没意义的大量匿名流量访问,对服务器压力有直接的影响。

2 nginx跨域配置

跨域的判断标准是基于浏览器的同源策略对每个xhr的请求判断,即一个xhr的请求要满足3个条件: 同域名,同端口和同协议。任一不满足则 判定当前xhr请求为跨域请求,如果被请求的服务端没有返回相关响应头来通知浏览器--本服务端接受跨域请求。则后面的请求会浏览器拦截下来。
这样做的用意是出于安全考虑。 就是当前访问的A域名,但如果要背后给B域名发送数据,就必须有B域名的许可, B域名的意思就是我愿意接受哪个域名 哪种方式什么样的请求头,在访问A域名的情况下还能发数据给我。 如果B域没有相关许可的声明,则浏览器会拦截跨域名的请求。

add_header Access-Control-Allow-Origin *; # <-- 允许的域名
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; # <-- 允许的请求方式
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; # <-- 允许的请求头字段

3 SpringBoot webFlux 跨域配置(引用)

We can also define a global CORS configuration by overriding the addCorsMappings() method of a WebFluxConfigurer implementation.

In addition, the implementation needs the @EnableWebFlux annotation to import the Spring WebFlux configuration in a plain Spring application. If we're using Spring Boot, then we only need this annotation if we want to override the auto-configuration:

Bean示例代码
@Configuration
@EnableWebFlux
public class CorsGlobalConfiguration implements WebFluxConfigurer {

@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/**")
.allowedOrigins("http://allowed-origin.com")
.allowedMethods("PUT")
.maxAge(3600);
}
}

As a result, we are enabling cross-origin request handling for that particular path pattern.

The default configuration is similar to the @CrossOrigin one, but with only the GET, HEAD, and POST methods allowed.

We can also combine this configuration with a local one:

  • For the multiple-value attributes, the resulting CORS configuration will be the addition of each specification
  • On the other hand, the local values will have precedence over the global ones for the single-value ones

Using this approach is not effective for functional endpoints, though.

4 SpringBoot webMVC 跨域配置

跟上面是一样的,也是配置一个过滤器

package com.zhuche.server.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.CorsRegistry;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;

@Configuration
@EnableWebFlux
public class CORSFilter implements WebFluxConfigurer {
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("PUT", "POST", "OPTION")
.maxAge(3600);
}