0%

cors 跨域问题处理

1. 介绍

跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对 Javascript 施加的安全限制。

同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域。具体场景如下所示:

跨域前端产生的报错如下所示,即从 http://localhost:8001 访问 http://localhost:88/api/sys/login 时被 CORS 策略阻止。

1
Access to XMLHttpRequest at 'http://localhost:88/api/sys/login' from origin 'http://localhost:8001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

2. 跨域流程

如下图是跨域的流程,具体关于非简单请求概念和其他跨域相关内容,可访问官网:跨源资源共享(CORS) - HTTP | MDN (mozilla.org)

跨域流程

3. 解决跨域方案

3.1 nginx 配置同源

根据产生跨域的原因,我们可以使用 nginx 对不同的请求配置成相同的地址和端口,然后在使用 nginx 内部进行请求转发,例如下图所示,这样可以有效解决跨域问题。

3.2 请求全局过滤

根据跨域流程我们知道浏览器首先会发送预检请求给服务器,然后根据服务器的响应是否允许实现跨域请求。因此我们只需要让服务器对指定的请求响应允许跨域请求即可,具体实现则是配置对应的响应头。常用的响应头如下所示:

  • Access-Control-Allow-Origin:支持哪些来源的请求跨域
  • Access-Control-Allow-Methods:支持哪些方法跨域
  • Access-Control-Allow-Credentials:跨域请求默认不包含 cookie,设置为 true 可以包含 cookie
  • Access-Control-Expose-Headers:跨域请求暴露的字段
    • CORS请求时,XMLHttpRequest 对象的 getResponseHeader() 方法只能拿到6个基本字段: Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
  • Access-Control-Max-Age:表明该响应的有效时间为多少秒。在有效时间内,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。

下面以 SpringBoot 为示例,通过过滤器实现对请求进行跨域处理,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 跨域处理配置
* @author zhengst
*/
@Configuration
public class GulimallCorsConfiguration {

@Bean
public CorsWebFilter corsWebFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration configuration = new CorsConfiguration();
// 允许暴露所有请求头
configuration.addAllowedHeader("*");
// 允许暴露所有请求方法
configuration.addAllowedMethod("*");
// 允许暴露所有请求来源
configuration.addAllowedOrigin("*");
// 支持请求包含 cookie
configuration.setAllowCredentials(true);
source.registerCorsConfiguration("/**", configuration);
return new CorsWebFilter(source);
}
}
------ 本文结束------