跨域基础概念
一、什么是跨域
跨域是指由于浏览器的同源策略限制,不同域的页面之间无法直接访问各自的内容。
同源策略定义:必须满足“三同”条件才属于同源,即:
- 同协议(如 http与https不同源)
- 同域名(如 www.kk.com 与 www.oo.com 不同源)
- 同端口(如 80 端口与 8080 端口不同源)
二、为什么需要跨域
浏览器的同源策略主要是为了防范 CSRF(跨站请求伪造)等安全攻击,但在实际开发中,经常需要跨域获取资源,例如:
- 前端项目(www.kk.com)通过 Ajax 请求后端接口(www.oo.com/getuser/uid/220305)获取用户数据
- 不同域名下的前后端分离项目进行数据交互
此时需要通过技术手段突破同源策略限制,实现合法的跨域访问。
跨域实现方式对比
| 实现方式 | 支持请求类型 | 适用场景 | 优缺点 |
|---|---|---|---|
| JsonP(前后端结合) | 仅支持 GET 请求 | 简单跨域数据获取 | 优点:实现简单;缺点:不支持 POST、安全性较低 |
| CORS(纯后端) | 支持 GET/POST/PUT/DELETE 等 | 大部分跨域场景 | 优点:标准方案、配置灵活;缺点:需后端单独配置 |
| Nginx 代理(纯后端) | 支持所有请求类型 | 生产环境推荐 | 优点:无需修改应用代码、统一管控、性能优;缺点:需配置 Nginx 服务器 |
注:JsonP 因局限性较强,本文不展开详细配置,如需了解可参考:https://blog.csdn.net/u014607184/article/details/52027879/
具体实现方案
一、CORS 方式(PHP 后端配置)
CORS 是 W3C 标准方案,通过在服务器端设置响应头 Access-Control-Allow-Origin 指定允许访问的域名,支持以下浏览器版本:
- IE:8&9(需使用 XDomainRequest)、10+
- Chrome:4+
- Firefox:3.5+
- Safari:4+
- Opera:12+
1. 允许单个域名跨域
在 PHP 响应文件中直接设置响应头,示例代码:
<?php
// 允许 www.kk.com 跨域访问
header('Access-Control-Allow-Origin: http://www.kk.com');
$data = array(
'name' => 'haveyb',
'age' => 26,
'sex' => 'man'
);
echo json_encode($data);
2. 允许多个域名跨域
通过判断请求来源域名,动态返回允许的 Origin 头,示例代码:
<?php
// 获取请求来源域名
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
// 允许跨域的域名列表
$allow_origin = array(
'http://www.kk.com',
'http://www.gg.com'
);
// 验证请求域名是否在允许列表中
if (in_array($origin, $allow_origin)) {
header('Access-Control-Allow-Origin: ' . $origin);
}
$data = array(
'name' => 'haveyb',
'age' => 26,
'sex' => 'man'
);
echo json_encode($data);
二、Nginx 代理方式(推荐)
利用同源策略仅作用于浏览器端的特性,通过 Nginx 服务器转发跨域请求,无需修改应用代码,配置步骤如下:
1. 前端代码(www.kk.com)
正常发送 Ajax 请求,目标地址为需要跨域的接口,示例代码(使用 jQuery):
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>测试 Ajax 跨域访问</title>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
</head>
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
type: "post", // 支持 POST 等所有请求类型
url: "http://www.oo.com/1.php", // 跨域接口地址
success: function(data) {
alert(data); // 成功接收跨域数据
},
error: function() {
alert("fail!!!,请刷新再试!");
}
});
});
</script>
<body>
<h1>测试跨域访问</h1>
</body>
</html>
2. 后端代码(www.oo.com)
无需额外配置跨域头,正常返回数据即可,示例代码:
<?php
$data = array(
'name' => 'haveyb',
'age' => 26,
'sex' => 'man'
);
echo json_encode($data);
3. Nginx 配置文件
在 Nginx 的 server 块中添加跨域相关配置,核心是通过 add_header 设置允许的 Origin 和请求方法:
server {
listen 80;
server_name www.oo.com ; # 被跨域的域名
root "G:\oo"; # 项目根目录
# 允许 www.kk.com 跨域访问
add_header Access-Control-Allow-Origin http://www.kk.com;
# 允许的请求方法
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
# 默认首页配置
location / {
index index.html index.htm index.php;
# autoindex on; # 可选,开启目录浏览
}
# PHP 解析配置
location ~ \.php(.*)$ {
fastcgi_pass 127.0.0.1:9000; # PHP-FPM 地址
fastcgi_index index.php;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
include fastcgi_params; # 引入 fastcgi 配置
}
}
4. 允许多个域名跨域(Nginx 进阶配置)
当需要允许多个域名跨域时,使用 Nginx 的 map 指令映射允许的域名列表,配置如下:
# 定义允许跨域的域名映射
map $http_origin $corsHost {
default 0; # 默认不允许跨域
"~http://www.kk.com" http://www.kk.com; # 允许的域名1
"~http://www.gg.com" http://www.gg.com; # 允许的域名2
}
server {
listen 80;
server_name www.oo.com ;
root "G:\oo";
# 动态设置允许的 Origin
add_header Access-Control-Allow-Origin $corsHost;
# 允许的请求方法
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
location / {
index index.html index.htm index.php;
}
location ~ \.php(.*)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
include fastcgi_params;
}
}
注意事项
-
安全性考量:避免设置
Access-Control-Allow-Origin: *(允许所有域名跨域),仅开放必要的可信域名,降低安全风险。 -
请求方法支持:
Access-Control-Allow-Methods需明确指定允许的请求类型,避免遗漏业务所需方法。 -
Nginx 配置生效:修改 Nginx 配置后,需执行
nginx -t验证配置正确性,再通过nginx -s reload重启 Nginx 使配置生效。 -
兼容性处理:针对 IE8/9 等低版本浏览器,若使用 CORS 方式需额外处理 XDomainRequest 对象,Nginx 代理方式无需额外兼容。
-
服务器负担:CORS 方式直接由应用服务器处理跨域逻辑,Nginx 代理方式通过反向代理转发请求,相比之下 Nginx 更擅长处理高并发,推荐生产环境使用。


