跨域问题
官方概念:
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
本质来说,是前端请求给到后端时候,请求头里面,有一个 Origin ,会带上 协议域名端口号等;后端接受到请求;如果没有在"返回头"里面放上"一些东西",返回的时候,浏览器根据"同源策略",就不会接受到返回;
注意:
shell
Sec-Fetch-Site 头部有几个可能的值:
same-origin: 请求源和目标是同一个站点
same-site: 请求源和目标在同一个站点组(比如 sub1.example.com 和 sub2.example.com)
cross-site: 跨站点请求
none: 请求不是由网站发起的(比如用户直接在地址栏输入URL)
我们来看两个例子:
这张是微博的任意页面刷新出来的东西:
这一个请求就没有跨域啥的,
然后我们看一个 B站的例子:
其实涉及到两个概念:
- Origin,(例如:https://www.bilibili.com)
- Host ,(例如:https://data.bilibili.com)
Origin是发出方。Host是目的地:这里可以看上面请求里B站的Host
解决
后端,返回的头里加上一个允许标记:给放过;
代码仅供参考,实际要根据业务需求情况,还有一些其他配置,这里关注:config.addAllowedOrigin("http://localhost:3000");
java
// 方案1:后端配置 CORS(跨域资源共享)
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 生产环境应该明确指定允许的域名
config.addAllowedOrigin("https://www.your-domain.com");
// 如果有多个域名,可以分别添加
config.addAllowedOrigin("https://admin.your-domain.com");
// 明确指定允许的请求方法,而不是使用 "*"
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
// 明确指定允许的头部,而不是使用 "*"
config.addAllowedHeader("Authorization");
config.addAllowedHeader("Content-Type");
// 是否允许发送Cookie
config.setAllowCredentials(true);
// 预检请求的有效期,单位为秒
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", config);
return new CorsFilter(source);
}
}
从前端也可以处理,生产环境的话,可以在Nginx里面配置
shell
server {
listen 80;
server_name example.com;
# 前端静态文件
location / {
root /path/to/dist;
try_files $uri $uri/ /index.html;
}
# 后端 API 代理
location /api {
# 跨域配置
add_header Access-Control-Allow-Origin '*'; # 生产环境建议配置具体域名
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
return 204;
}
# 反向代理配置
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
时光海海,日常焦虑 🍀,加油