1. 什么是跨域?
- 简单来说:不同域名/端口/协议之间的请求被浏览器阻止了,这就是跨域问题。
- 必须同源浏览器才允许互相访问数据,跨域的参照物是当前网页的域名 。
| 条件 | 示例 |
|---|---|
| 协议 | http:// 或 https:// |
| 域名 | example.com |
| 端口 | :80, :3000 |
| 比较项 | 页面名片 (A) | 请求名片 (B) | 结果 |
|---|---|---|---|
| 协议 | https://example.com | http://example.com | 跨域 (协议不同) |
| 域名 | https://api.example.com | https://web.example.com | 跨域 (子域名不同) |
| 端口 | https://example.com(https://me.com/):8080 | https://example.com:9000 | 跨域 (端口不同) |
| 全匹配 | https://example.com | https://example.com/data | 同源 (安全通过) |
2. 为什么会有跨域限制?
跨域(CORS)是浏览器的一种保护机制。
- 假设你登录了微博
weibo.com,浏览器存了你的登录状态(Cookie)。 - 此时你打开了一个看小说的网页
novel.com。 - 如果没跨域限制:
novel.com里的 JS 脚本可以直接写一段代码fetch('https://weibo.com/delete-post')。 - 后果: 浏览器会带着你的 Cookie 发出请求,微博服务器以为是你本人想删贴,于是操作成功。
浏览器设立跨域限制的逻辑是:“除非
weibo.com明确告诉我它信任novel.com,否则我不允许novel.com的脚本去碰weibo.com的数据。”
3. JS 发送请求时的过程
1.域名一致(同源)
- 浏览器的判断: 比较发现“协议+域名+端口”完全一致。
- 行为: 直接发送请求。 不会有任何额外的询问,就像你在家里从厨房走到卧室拿东西一样自然。
2.情况二:域名不一致(跨域)
这时浏览器会根据请求的内容,决定是先斩后奏还是先请示再行动。
- 简单请求 —— “先斩后奏”
请求很“简单”(比如普通的 GET 或 POST)
- 复杂请求 —— “先请示再行动”
请求比较“高级”(比如 PUT、DELETE,或者你在 Header 里加了 Authorization 令牌)
4.跨域的常见解决方案
-
CORS
原理: 后端设置响应头,告诉浏览器:“我允许这个网站访问我的资源。
Spring MVC设置允许跨域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18@Configuration @RequiredArgsConstructor public class CorsConfig implements WebMvcConfigurer { private final CorsProperties corsProperties; @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") //允许发送cookie .allowCredentials(true) //放行哪些域名 因为allowCredentials要发送cookie 所以必须是具体的源地址 .allowedOrigins(corsProperties.getAllowOrigins().toArray(new String[0])) .allowedHeaders("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .exposedHeaders("*"); } } -
Nginx代理转发
原理:跨域问题本质是浏览器的安全校验,因此只要绕过浏览器就好了。先将请求发给Nginx服务器,然后Nginx再将请求转发给后端,后端返回结果给Nginx服务器,Nginx再返回给前端。看上去是同源
|
|
5.一些小细节
事实上:当你从 a.com 的网页向 b.com/api 发送 JS 请求时,浏览器会自动在 HTTP 请求头(Headers)里加上:
-
Origin字段
- 内容:
Origin: http://a.com - 作用: 它是专门为了 CORS(跨域资源共享) 设计的。它只包含“协议+域名+端口”,不包含具体的路径。
- 浏览器的逻辑: “我得告诉
b.com,这行 JS 代码是a.com指使我运行的。b.com你自己看着办,准不准它读你的数据。”
- 内容:
-
Referer 字段
- 内容:
Referer: http://a.com/pages/index.html - 作用: 它比 Origin 更详细,包含了具体的来源页面全路径。
- 浏览器的逻辑: “我得告诉
b.com,用户是从哪一个具体的页面跳过来的。”
- 内容: