网站跨域问题解决方案(三种方法)
概述
跨域问题是前后端分离开发中最常见的障碍之一。浏览器出于安全考虑,默认禁止页面请求不同源(协议、域名、端口任一不同)的资源。本文整理了多种跨域解决方案,从服务端配置到开发调试,覆盖不同场景。
什么是跨域
当浏览器向一个不同源的 URL 发起请求时,就会触发跨域限制。同源必须满足三个条件完全一致:
- 协议相同:http vs https 算不同源
- 域名相同:www.example.com vs api.example.com 算不同源
- 端口相同:8080 vs 8081 算不同源
注意:跨域限制是浏览器的行为,服务端之间的请求不受此限制。这也是很多解决方案的出发点。
方法一:升级 HTTPS(推荐首选)
将系统从 HTTP 升级到 HTTPS。现代浏览器对 HTTPS 站点的跨域策略更宽松,同时也是安全最佳实践。
具体步骤:
- 申请 SSL 证书(推荐 Let's Encrypt 免费证书)
- 在 Nginx/Apache 中配置证书
- 确保前端和后端都使用 HTTPS
- 将页面中的 HTTP 资源引用替换为 HTTPS 或协议相对路径
升级后,同协议下的跨域请求配合 CORS 头即可正常工作。
方法二:浏览器关闭安全检查(仅限开发调试)
- 浏览器打开
edge://flags/#local-network-access-check(Chrome 用chrome://flags/#block-insecure-private-network-requests) - 找到 Local Network Access Checks(或 Block insecure private network requests),设置为 Disabled
- 重启浏览器
此方法仅适用于本地开发调试,绝不要在生产环境使用。建议开发时优先使用方法三(CORS 头),从根源解决问题。
方法三:服务端配置 CORS 跨域协议头(最常用)
在服务端响应中添加 CORS 头,告诉浏览器允许跨域访问。
各字段详解
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
Access-Control-Max-Age: 3600
Access-Control-Allow-Credentials: true| 字段 | 说明 |
|---|---|
| Access-Control-Allow-Origin | 允许的源,* 表示所有。生产环境建议指定具体域名 |
| Access-Control-Allow-Methods | 允许的 HTTP 方法 |
| Access-Control-Allow-Headers | 允许的请求头,自定义头需要在此声明 |
| Access-Control-Max-Age | 预检请求缓存时间(秒),减少 OPTIONS 请求次数 |
| Access-Control-Allow-Credentials | 是否允许携带 Cookie,设为 true 时 Origin 不能为 * |
Nginx 配置方式
location /api/ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
if ($request_method = OPTIONS) {
return 204;
}
proxy_pass http://127.0.0.1:8080;
}Node.js / Express 配置
const cors = require("cors");
app.use(cors({
origin: "https://www.your-site.com",
methods: ["GET", "POST", "PUT", "DELETE"],
credentials: true
}));PHP 配置
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
if ($_SERVER["REQUEST_METHOD"] === "OPTIONS") {
http_response_code(204);
exit;
}方法四:CORS 预检请求(OPTIONS)详解
对于非简单请求(如 Content-Type 为 application/json、自定义头、PUT/DELETE 方法),浏览器会先发送一个 OPTIONS 预检请求,询问服务端是否允许该跨域请求。服务端返回正确的 CORS 头后,浏览器才会发送真正的请求。
简单请求的条件:
- 方法为 GET、HEAD、POST 之一
- Content-Type 为 text/plain、multipart/form-data、application/x-www-form-urlencoded 之一
- 无自定义请求头
不满足以上任一条件即为非简单请求,会触发预检。
方法五:JSONP(仅 GET,已过时)
利用 script 标签不受跨域限制的特性,动态创建 script 标签获取数据。仅支持 GET 请求。
// 前端
function jsonp(url, callback) {
var script = document.createElement("script");
script.src = url + "?callback=" + callback;
document.body.appendChild(script);
}
// 后端返回 callback({"data": "hello"})JSONP 存在安全风险(XSS),现代开发中已不推荐使用,建议用 CORS 替代。
方法六:服务端代理(反向代理)
在同源的服务端设置代理,将跨域请求转发到目标服务器。因为跨域限制只存在于浏览器,服务端之间的请求不受限。
// Nginx 反向代理示例
location /api/ {
proxy_pass http://api.example.com/; // 转发到真实 API
}前端只需请求同源的 /api/xxx,Nginx 自动转发到目标,完美绕过跨域限制。
方法七:WebSocket
WebSocket 协议不受同源策略限制,可以在不同源之间建立全双工通信。适用于实时数据推送场景。
方案选择建议
| 场景 | 推荐方案 |
|---|---|
| 前后端都是自己的服务 | Nginx 反向代理(方法六) |
| API 供第三方调用 | CORS 头(方法三) |
| 本地开发调试 | 浏览器关闭检查(方法二)或 CORS 允许 localhost |
| 活字格服务端命令 | CORS 头 + Nginx 配置 |
| 实时推送 | WebSocket(方法七) |
活字格中的跨域配置
活字格的服务端命令可以通过配置 CORS 头实现跨域调用:
location /Forguncy/ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
if ($request_method = OPTIONS) {
return 204;
}
proxy_pass http://127.0.0.1:8081;
}常见错误排查
| 错误信息 | 原因 | 解决 |
|---|---|---|
| No Access-Control-Allow-Origin header | 服务端未返回 CORS 头 | 添加 Access-Control-Allow-Origin |
| Credentials flag is true but origin is * | 携带 Cookie 但 Origin 为通配符 | 指定具体 Origin 而非 * |
| Method PUT is not allowed | 未在 Allow-Methods 中声明该方法 | 添加对应 HTTP 方法 |
| Request header field xxx is not allowed | 自定义请求头未声明 | 在 Allow-Headers 中添加 |
总结
- 最推荐:Nginx 反向代理,同源访问,零跨域问题
- 最通用:CORS 响应头,适合对外开放的 API
- 开发调试:浏览器关闭安全检查,但别用在生产环境
- 核心原理:跨域是浏览器限制,绕过思路是让浏览器以为同源,或者让服务端明确说我允许
暂无评论
快来发表第一条评论吧!