跨域产生的原因及解决方案
Kiml Lv5
  • 前言
    面试必会,总结一下

  • 更新

1
24-08-22 初始记录

跨域的原因

跨域是是因为浏览器的同源策略限制,是浏览器的一种安全机制,服务端之间是不存在跨域的。

所谓同源指的是两个页面具有相同的协议、主机和端口,三者有任一不相同即会产生跨域。

跨域举例

当前页面 url 被请求页面 url 是否跨域 原因
http://www.test.com/ http://www.test.com/index.html 同源(协议、域名、端口号相同)
http://www.test.com/
https://www.test.com/index.html 跨域 协议不同
http://www.test.com/ http://www.baidu.com/ 跨域 主域名不同
http://www.test.com/
http://blog.test.com/ 跨域 子域名不同
http://www.test.com:8080/
http://www.test.com:7071/ 跨域 端口号不同

跨域的解决办法

以下跨域解决方式选择一种,重复配置不会生效。

Java 配置

  1. 使用 @CrossOrigin 注解实现跨域【局域类跨域】(一般不用,没有记录)

  2. 通过配置文件实现跨域【全局跨域】

  3. 通过 CorsFilter 对象实现跨域【全局跨域】

  4. 通过 Response 对象实现跨域【局域方法跨域】(一般不用,没有记录)

  5. 通过实现 ResponseBodyAdvice 实现跨域【全局跨域】(一般不用,没有记录)

  1. 通过配置文件实现跨域(重写 WebMvcConfigurer)

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
public class CorsConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "OPTIONS", "DELETE", "PUT", "PATCH")
.maxAge(3600);
}
}
  1. 返回新的 CorsFilter(跨域配置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Configuration
public class GlobalCorsConfig {

@Bean
public CorsFilter corsFilter() {
//1. 添加 CORS配置信息
CorsConfiguration config = new CorsConfiguration();
// 放行哪些原始域
config.addAllowedOrigin("*");
// 是否发送 Cookie
config.setAllowCredentials(true);
// 放行哪些请求方式
config.addAllowedMethod("*");
// 放行哪些原始请求头部信息
config.addAllowedHeader("*");
// 暴露哪些头部信息
config.addExposedHeader("*");
//2. 添加映射路径
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**",config);
//3. 返回新的CorsFilter
return new CorsFilter(corsConfigurationSource);
}
}

Nginx 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server {
listen 80;
server_name your_domain.com;
location /api {
# 允许跨域请求的域名,* 表示允许所有域名访问
add_header 'Access-Control-Allow-Origin' '*';

# 允许跨域请求的方法
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

# 允许跨域请求的自定义 Header
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept';

# 允许跨域请求的 Credential
add_header 'Access-Control-Allow-Credentials' 'true';

# 预检请求的存活时间,即 Options 请求的响应缓存时间
add_header 'Access-Control-Max-Age' 3600;

# 处理预检请求
if ($request_method = 'OPTIONS') {
return 204;
}
}
# 其他配置...
}

Gateway 网关配置

  1. 通过在配置文件中配置跨域实现。

  2. 通过在框架中添加 CorsWebFilter 来解决跨域问题。

  1. 通过在配置文件中配置跨域实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]': # 匹配所有请求
allowedHeaders: "*"
allowedOrigins: "*" #跨域处理 允许所有的域
allowedMethods: # 支持的方法
- GET
- POST
- PUT
- DELETE
- OPTIONS
  1. 通过在框架中添加 CorsWebFilter 来解决跨域问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 在 Spring-Framework 从 5.3 版本之前,使用以下代码可以让 Spring Cloud Gateway 网关允许跨域:
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
// 这里仅为了说明问题,配置为放行所有域名,生产环境请对此进行修改
config.addAllowedOrigin("*");
// 放行的请求头
config.addAllowedHeader("*");
// 放行的请求类型,有 GET, POST, PUT, DELETE, OPTIONS
config.addAllowedMethod("*");
// 暴露头部信息
config.addExposedHeader("*");
// 是否允许发送 Cookie
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}

// 而 Spring-Framework 5.3 版本之后,关于 CORS 跨域配置类 CorsConfiguration 中将 addAllowedOrigin 方法名修改为 addAllowedOriginPattern,因此配置了变成了以下这样:
@Configuration
public class GlobalCorsConfig {

@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
// 这里仅为了说明问题,配置为放行所有域名,生产环境请对此进行修改
config.addAllowedOriginPattern("*");
// 放行的请求头
config.addAllowedHeader("*");
// 放行的请求类型,有 GET, POST, PUT, DELETE, OPTIONS
config.addAllowedMethod("*");
// 暴露头部信息
config.addExposedHeader("*");
// 是否允许发送 Cookie
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
访客数 访问量