跨域 (CORS) 原理:浏览器的“尽职保镖”

🚫 那个让前端抓狂的红字报错

作为前端开发,你一定见过这个经典的报错:

Access to XMLHttpRequest at 'http://api.server.com' from origin 'http://localhost:8080' has been blocked by CORS policy

这时候你可能会想:"我就调个接口,为什么浏览器要拦着我?"

其实,这不是浏览器在故意刁难你,而是它在保护用户 。这个机制叫做同源策略 (Same-Origin Policy)


🏠 什么是"同源策略"?

1. 核心概念

浏览器有一个默认的安全规则:A 网站的 JavaScript,不能随便读取 B 网站的数据

除非 A 和 B 是"一家人"(同源)。

2. 怎样才算"一家人"?

必须同时满足以下三个条件,才算同源

  1. 协议相同 (Protocol):都是 http 或都是 https
  2. 域名相同 (Domain):都是 www.example.com
  3. 端口相同 (Port):都是 80 (或都不写)。

只要有一个不一样,就是跨域

当前页面 请求接口 结果 原因
http://a.com http://a.com/api ✅ 同源 一家人
http://a.com https://a.com/api ❌ 跨域 协议不同 (http vs https)
http://a.com http://b.com/api ❌ 跨域 域名不同
http://a.com http://a.com:8080 ❌ 跨域 端口不同 (80 vs 8080)

👮‍♂️ 为什么要有这个策略?(比喻)

想象一下:

  • 浏览器 = 你的小区 🏘️
  • 同源策略 = 小区保安 👮‍♂️
  • 恶意网站 = 推销员 🦹

如果你登录了银行网站 (bank.com),银行给你发了一张通行证 (Cookie) 存在浏览器里。

然后你不小心点开了恶意网站 (evil.com)。如果没有同源策略:

  1. evil.com 的代码悄悄向 bank.com 发送请求:"我要转账"。
  2. 浏览器发现你有 bank.com 的通行证,于是就带上通行证发请求了。
  3. 银行一看通行证是真的,钱就被转走了! 💸

但是,因为有同源策略 (保安)

保安发现:"哎?你是 evil.com (推销员),你想去 bank.com (金库) 拿东西?不行!你的工牌对不上!"

于是请求被拦截,你的钱保住了。


🔓 怎么解决跨域?(三种常见方案)

虽然同源策略是为了安全,但在开发中,我们的前端 (localhost:8080) 和后端 (api.com) 往往不在同一个域,确实需要通信。怎么办?

1. CORS (官方推荐:发通行证) ✅

CORS 全称是 Cross-Origin Resource Sharing (跨域资源共享)。

原理很简单:后端服务器告诉浏览器:"在这个名单里的人,可以放行。"

流程图解:

🖥️ 后端 (api.com) 🌍 浏览器 (localhost) 🖥️ 后端 (api.com) 🌍 浏览器 (localhost) 准备发送复杂请求 (如带Token) 预检请求 (Preflight) 查白名单:允许!✅ OPTIONS /api (有人在吗?我能进吗?) 200 OK (Header: Allow localhost) GET /api (真正的请求) {data: ...} (拿到数据)

流程:
  1. 浏览器 :我想去 api.com 拿数据,但我来自 localhost:8080,行吗?
  2. 浏览器 (如果是复杂请求,先发一个 OPTIONS 预检请求):有人在吗?我能进吗?
  3. 后端服务器 :收到,我查一下白名单... 好的,允许 localhost:8080 访问!(返回响应头 Access-Control-Allow-Origin: http://localhost:8080)
  4. 浏览器 :看到后端点头了,保安放行,数据拿到。

后端代码示例 (Node.js/Express):

javascript 复制代码
app.use((req, res, next) => {
  // 允许 localhost:8080 访问
  res.header('Access-Control-Allow-Origin', 'http://localhost:8080');
  // 允许的方法
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  next();
});

2. 代理 (Proxy) (欺骗保安) 🎭

同源策略只限制浏览器,不限制服务器! 服务器和服务器之间通信是自由的。

我们可以找一个中间人 (代理服务器),让他去帮我们拿数据。

原理:
  1. 前端 (localhost:8080) 不直接找后端,而是找 本地代理 (localhost:8080/api)。
  2. 保安 一看:你找你自己家的人,同源,放行!
  3. 本地代理 悄悄去 后端 (api.com) 把数据拿回来。
  4. 本地代理 再把数据给 前端

Vue 配置示例 (vue.config.js):

javascript 复制代码
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://api.com', // 真正的后端地址
        changeOrigin: true,       // 告诉后端:我是从 api.com 来的 (伪装)
        pathRewrite: { '^/api': '' }
      }
    }
  }
}

3. Nginx 反向代理 (生产环境常用) 🔄

原理和上面一样,只不过是在部署时,用 Nginx 做这个"中间人"。

Nginx 配置:

nginx 复制代码
server {
    listen 80;
    server_name my-website.com;

    # 前端文件
    location / {
        root /usr/share/nginx/html;
    }

    # 接口转发
    location /api/ {
        proxy_pass http://api-server.com/; # 转发给后端
    }
}

这样对浏览器来说,前端和接口都在 my-website.com 下,完美同源


🧪 进阶知识:面试必问细节

1. 简单请求 vs 复杂请求 (为什么会有 OPTIONS?) 🕵️

有时候你会发现浏览器自动 多发了一个 OPTIONS 请求,这叫预检请求 (Preflight)

  • 简单请求 (Simple Request) :直接发,不预检。
    • 方法是 GET, HEAD, POST
    • Header 只有常见的 Accept, Content-Type 等。
    • Content-Type 只能是 text/plain, multipart/form-data, application/x-www-form-urlencoded
  • 复杂请求 (Preflighted Request) :先发 OPTIONS 问路。
    • 用了 PUT, DELETE 方法。
    • 发送了 JSON 数据 (Content-Type: application/json)。
    • 加了自定义 Header (如 Authorization, Token)。

结论 :大部分现代前后端分离应用(发 JSON、带 Token)都是复杂请求 ,所以看到 OPTIONS 不要慌,那是浏览器在礼貌问路。

默认情况下,跨域请求不带 Cookie。如果你需要登录态,必须两边都配合:

  1. 前端 (axios) :开启 withCredentials: true
  2. 后端
    • Access-Control-Allow-Credentials: true (允许带证件)。
    • Access-Control-Allow-Origin 不能*,必须写死具体域名 (如 http://localhost:8080)。

3. JSONP (时代的眼泪) 👴

在 CORS 还没普及的年代,前辈们发现 <script src="..."> 标签不受同源策略限制(你可以引用百度的 JS)。

于是利用 <script> 偷运数据,这就是 JSONP。现在除了老旧系统,基本不用了。


🧠 总结

  1. 跨域 是因为浏览器的同源策略,为了保护你的安全。
  2. 同源 = 协议域名端口 三者都一样。
  3. 解决办法
    • CORS:后端加响应头,发"通行证"。(最常用)
    • Proxy:前端/Nginx 做代理,让"中间人"去拿数据。(开发/生产环境常用)
相关推荐
XLYcmy2 小时前
高级密码生成器程序详解:专门设计用于生成基于用户个人信息的密码猜测组合
开发语言·数据结构·python·网络安全·数据安全·源代码·口令安全
没有bug.的程序员16 小时前
服务安全:内部服务如何防止“裸奔”?
java·网络安全·云原生安全·服务安全·零信任架构·微服务安全·内部鉴权
Bruce_Liuxiaowei1 天前
(2025最后一篇博客)Metasploit框架攻击Windows实例:三种渗透路径
网络·windows·网络安全·网络攻击模型
week_泽1 天前
Dvwa靶场搭建_错误汇总
web安全·网络安全·靶场·dvwa
钦拆大仁1 天前
聊一聊跨域错误CORS
web·跨域
信创天地2 天前
信创国产化数据库的厂商有哪些?分别用在哪个领域?
数据库·python·网络安全·系统架构·系统安全·运维开发
秋4272 天前
防火墙基本介绍与使用
linux·网络协议·安全·网络安全·架构·系统安全
Bug.ink2 天前
BUUCTF——WEB(4)
前端·网络安全·靶场·ctf·buuctf