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 方法

  • 自定义请求头(如 AuthorizationX-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

相关推荐
caimouse9 小时前
TDI (传输驱动接口 Transport Driver Interface) 详细分析
网络协议
weixin_4462608510 小时前
从被动镜像到主动智能体:面向网络物理人工智能的整体论数字孪生(HDT-Net)
网络·人工智能
ZJH__GO10 小时前
网络编程v4pro--实现聊天室文件传输功能
java·服务器·网络·计算机网络
shengnan_wsn13 小时前
【协议】【TCP】
网络·网络协议·tcp/ip
烟雨江南78513 小时前
2026汽车制造与新能源整车柔性产线Agentic-Workflow白皮书:跨APS_MES_ERP多智能体动态排产与装配容错实战
大数据·网络·人工智能·自动化·ai客服·企业agent
小僧景贤13 小时前
CAN调试全套配件+详细实操使用方法(从零排查、步骤落地、现场通用)
网络·can通信·嵌入式通信
消失的旧时光-194313 小时前
第 3 篇:机器人 TCP 长连接如何稳定运行?心跳、掉线检测与自动重连
网络协议·tcp/ip·机器人
迪康Defender14 小时前
从静态存储到动态流转:终端透明加密两种模式实战解析
运维·服务器·网络·数据库·其他
振浩微433射频芯片14 小时前
用TU2303B双向无线模块打通标准化智能家居接入:433MHz方案的落地优势指南
服务器·网络·人工智能
不弃君15 小时前
在 Windows 上用 MinGW 搭建 lwIP 调试环境:方法与踩坑实录
windows·网络协议·tcp/ip·嵌入式·mingw·lwip