HTTP 完全指南(最终篇):CORS 跨域资源共享深度详解

引言

前端开发中最让人头疼的报错之一:

Access to XMLHttpRequest at 'http://api.example.com/user'

from origin 'http://www.example.com' has been blocked by CORS policy:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

这就是跨域问题 。很多开发者的第一反应是"后端加个 Access-Control-Allow-Origin: * 就好了",但为什么加这个就能解决?什么时候该用 *?什么时候不该用?带 Cookie 的跨域请求怎么处理?

本文将彻底讲透 CORS 的原理、分类和解决方案。

第一部分:同源策略

一、什么是同源

两个 URL 同源,必须满足三个条件完全相同:

条件 URL1 URL2 是否同源
协议 http:// https:// ❌ 协议不同
域名 www.a.com api.a.com ❌ 子域名不同
端口 :80 :8080 ❌ 端口不同
全部相同 http://a.com:80/a http://a.com:80/b ✅ 同源

同源策略限制的是:

  • Cookie、LocalStorage 的读取

  • DOM 的访问

  • AJAX 请求的发送

不受同源策略限制的:

  • <script src="..."> 加载 JS

  • <img src="..."> 加载图片

  • <link href="..."> 加载 CSS

  • <a> 链接跳转

  • 表单提交

这就是为什么 JSONP 能跨域------它利用了 <script> 标签不受同源策略限制的"漏洞"。


第二部分:CORS 的分类

浏览器把跨域请求分为两类:简单请求 和非简单请求。

一、简单请求的三个条件(必须同时满足)

1. 请求方法是以下三种之一:

  • GET

  • HEAD

  • POST

2. 只包含以下请求头(不能有自定义头):

  • Accept

  • Accept-Language

  • Content-Language

  • Content-Type(仅限三种值)

3. Content-Type 只能是:

  • text/plain

  • multipart/form-data

  • application/x-www-form-urlencoded

任何不满足以上条件的就是非简单请求。比如:

  • PUT、DELETE、PATCH 方法

  • 自定义请求头(如 Authorization、X-Custom-Header)

  • Content-Type 是 application/json

二、简单请求的流程

核心头:

请求头:Origin: http://www.example.com

响应头:Access-Control-Allow-Origin: http://www.example.com

三、非简单请求(预检请求)

预检请求相关的头:

头(请求) 含义
Access-Control-Request-Method 告知真实请求的方法
Access-Control-Request-Headers 告知真实请求的自定义头
头(响应) 含义
Access-Control-Allow-Origin 允许的源
Access-Control-Allow-Methods 允许的方法
Access-Control-Allow-Headers 允许的请求头
Access-Control-Max-Age 预检缓存时间(秒),时间内不发第二次预检

默认情况下,跨域请求不携带 Cookie。

一、前端设置

javascript 复制代码
// 原生 XHR
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;  // 关键!

// Fetch
fetch('http://api.example.com/user', {
    credentials: 'include'    // 关键!
});

二、后端设置

javascript 复制代码
响应头:
Access-Control-Allow-Origin: http://www.example.com   ← 不能用 *!
Access-Control-Allow-Credentials: true                ← 必须

两条硬规则:

  1. Access-Control-Allow-Origin 不能是 *,必须是具体的源

  2. 必须加 Access-Control-Allow-Credentials: true

第四部分:完整 CORS 响应头速查

响应头 作用 示例
Access-Control-Allow-Origin 允许的源 http://www.example.com 或 *
Access-Control-Allow-Credentials 允许携带 Cookie true
Access-Control-Allow-Methods 允许的 HTTP 方法 GET, POST, PUT, DELETE
Access-Control-Allow-Headers 允许的请求头 Authorization, Content-Type
Access-Control-Expose-Headers 允许 JS 读取的响应头 X-Total-Count
Access-Control-Max-Age 预检缓存时间 86400(24小时)

第五部分:常见跨域解决方案对比

方案 原理 优点 缺点
CORS 服务器加响应头 标准方案,功能完整 需要后端配合
JSONP <script> 标签不受跨域限制 兼容老浏览器 只支持 GET
反向代理 同域下转发请求 彻底避开跨域 需要运维配置
postMessage HTML5 跨文档通信 iframe 间通信 需双方配合
WebSocket 不受同源策略限制 双向通信 需要服务器支持

JSONP 示例

html 复制代码
<script>
function handleResponse(data) {
    console.log(data);
}
</script>
<script src="http://api.example.com/user?callback=handleResponse"></script>
javascript 复制代码
// 服务器返回
handleResponse({"name": "张三", "age": 20});

JSONP 已过时,新项目统一用 CORS。

反向代理(开发环境常用)

javascript 复制代码
// vite.config.js
export default {
    server: {
        proxy: {
            '/api': {
                target: 'http://api.example.com',
                changeOrigin: true
            }
        }
    }
};

前端请求 /api/user → 开发服务器转发到 http://api.example.com/api/user → 同源,无跨域问题。


第六部分:面试题

1. Q:什么是同源策略?

A:浏览器安全机制。两个 URL 的协议、域名、端口必须完全相同才算同源。同源策略限制不同源之间的 Cookie 读取、DOM 访问、AJAX 请求。

2. Q:简单请求和非简单请求的区别?

A:简单请求(GET/POST/HEAD + 特定 Content-Type)直接发送,浏览器自动带 Origin 头。非简单请求(PUT/DELETE、自定义头、application/json)先发 OPTIONS 预检请求,服务器允许后才发真实请求。

3. Q:跨域带 Cookie 需要什么配置?

A:前端设置 withCredentials: true;后端设置 Access-Control-Allow-Origin 为具体源(不能用 *)+ Access-Control-Allow-Credentials: true;Cookie 本身需要 SameSite=None; Secure。

4. Q:为什么跨域请求的响应被拦截了,但请求实际已发出?

A:浏览器的同源策略只拦截 JS 读取响应,不拦截请求的发送。服务器确实收到了请求并处理了。这是防止恶意网站读取用户数据,但不阻止数据提交。

5. Q:CORS 和 JSONP 选哪个?

A:CORS。JSONP 只支持 GET、有 XSS 风险、已过时。新项目统一用 CORS,需要兼容老 IE 时才考虑 JSONP。


总结

一、CORS 核心流程

二、关键响应头

javascript 复制代码
Access-Control-Allow-Origin: http://www.example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Max-Age: 86400

三、一句话记忆

同源策略限制跨域 AJAX,CORS 通过服务器返回 Access-Control-Allow-Origin 等响应头来授权跨域访问。简单请求直接带 Origin,非简单请求先发 OPTIONS 预检。带 Cookie 需要前端开 withCredentials + 后端指定具体 Origin 并开 Credentials。

相关推荐
鹿鸣天涯10 分钟前
2026年下半年网络规划设计师论文
网络·计算机网络·网络规划设计师
echome88838 分钟前
Linux 定时任务:crontab 写法与常见失效原因
linux·运维·网络·定时任务·crontab
从琳开始9891 小时前
从Socket到TCP回显服务器:Java网络编程完整指南
java·服务器·网络·tcp/ip·java-ee
誰能久伴不乏1 小时前
用 UDP 做一条“可靠“的控制通道
c++·qt·网络协议·udp
跨境数据猎手1 小时前
HTTP 响应体编码与压缩:识别、解码
网络协议·http·ios
安易算力2 小时前
智算中心网络架构:RDMA/IB/以太网选型深度解析与优化实践
网络·架构·php
B1118521Y463 小时前
网络安全案例1:远程登陆实战
网络
|_⊙3 小时前
传输层协议UDP和TCP
网络·tcp/ip·udp
凯基迪科技3 小时前
瑞萨R5F100解密 R8C/RL78 MCU 固件读取与保护机制详解
服务器·网络·单片机
承渊政道3 小时前
Linux网络学习【五种IO模型与⾮阻塞IO】
linux·网络·学习·ubuntu·io模型·非阻塞io