目錄
- 什么是跨域
- 跨域場(chǎng)景
- 解決跨域的四種方式
什么是跨域
- 域: 是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本
- 跨域: 它是由瀏覽器的 同源策略 造成的,是瀏覽器對(duì)
JavaScript實(shí)施的安全限制,所謂同源(即指在同一個(gè)域)就是兩個(gè)頁(yè)面具有相同的協(xié)議protocol,主機(jī)host和端口號(hào)port則就會(huì)造成 跨域

跨域場(chǎng)景
場(chǎng)景的跨域場(chǎng)景有哪些,請(qǐng)參考下表
| 當(dāng)前url | 請(qǐng)求url | 是否跨域 | 原因 |
|---|---|---|---|
| http://www.autofelix.cn | http://www.autofelix.cn/api.php | 否 | 協(xié)議/域名/端口都相同 |
| http://www.autofelix.cn | https://www.autofelix.cn/api.php | 是 | 協(xié)議不同 |
| http://www.autofelix.cn | http://www.rabbit.cn | 是 | 主域名不同 |
| http://www.autofelix.cn | http://api.autofelix.cn | 是 | 子域名不同 |
| http://www.autofelix.cn:80 | http://www.autofelix.cn:8080 | 是 | 端口不同 |
解決跨域的四種方式
- nginx的反向代理
- 使用
nginx反向代理實(shí)現(xiàn)跨域,是最簡(jiǎn)單的跨域方式 - 只需要修改
nginx的配置即可解決跨域問(wèn)題,支持所有瀏覽器,支持session,不需要修改任何代碼,并且不會(huì)影響服務(wù)器性能
// nginx配置
server {
listen 81;
server_name www.domain1.com;
location / {
proxy_pass http://www.domain2.com:8080; #反向代理
proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
index index.html index.htm;
# 當(dāng)用webpack-dev-server等中間件代理接口訪(fǎng)問(wèn)nignx時(shí),此時(shí)無(wú)瀏覽器參與,故沒(méi)有同源限制,下面的跨域配置可不啟用
add_header Access-Control-Allow-Origin http://www.domain1.com; #當(dāng)前端只跨域不帶cookie時(shí),可為*
add_header Access-Control-Allow-Credentials true;
}
}
jsonp請(qǐng)求
jsonp是服務(wù)器與客戶(hù)端跨源通信的常用方法。最大特點(diǎn)就是簡(jiǎn)單適用,兼容性好兼容低版本IE,缺點(diǎn)是只支持get請(qǐng)求,不支持post請(qǐng)求- 原理時(shí)網(wǎng)頁(yè)通過(guò)添加一個(gè)
<script>元素,向服務(wù)器請(qǐng)求json數(shù)據(jù),服務(wù)器收到請(qǐng)求后,將數(shù)據(jù)放在一個(gè)指定名字的回調(diào)函數(shù)的參數(shù)位置傳回來(lái)
//jquery實(shí)現(xiàn)
<script>
$.getJSON('http://autofelix.com/api.php&callback=?', function(res) {
// 處理獲得的數(shù)據(jù)
console.log(res)
});
</script>
- 后端語(yǔ)言代理
- 可以通過(guò)一種沒(méi)有跨域限制的語(yǔ)言中轉(zhuǎn)一下,通過(guò)后端語(yǔ)言去請(qǐng)求資源,然后再返回?cái)?shù)據(jù)
- 比如
http://www.autofelix.cn需要調(diào)用http://api.autofelix.cn/userinfo去獲取用戶(hù)數(shù)據(jù),因?yàn)樽佑蛎煌瑫?huì)有跨域限制 - 可以先請(qǐng)求
http://www.autofelix.cn下的php文件,比如http://www.autofelix.cn/api.php,然后再通過(guò)該php文件返回?cái)?shù)據(jù)
// api.php 文件中的代碼
public function getCurl($url, $timeout = 5)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
$result = getCurl('http://api.autofelix.cn/userinfo');
return $result;
- 后端語(yǔ)言的設(shè)置
- 主要通過(guò)后端語(yǔ)言主動(dòng)設(shè)置跨域請(qǐng)求,這里以
php作為案例
// 允許所有域名訪(fǎng)問(wèn)
header('Access-Control-Allow-Origin: *');
// 允許單個(gè)域名訪(fǎng)問(wèn)
header('Access-Control-Allow-Origin: https://autofelix.com');
// 允許多個(gè)自定義域名訪(fǎng)問(wèn)
static public $originarr = [
'https://autofelix.com',
'https://baidu.com',
'https://csdn.net',
];
// 獲取當(dāng)前跨域域名
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
if (in_array($origin, self::$originarr)) {
// 允許 $originarr 數(shù)組內(nèi)的 域名跨域訪(fǎng)問(wèn)
header('Access-Control-Allow-Origin:' . $origin);
// 響應(yīng)類(lèi)型
header('Access-Control-Allow-Methods:POST,GET');
// 帶 cookie 的跨域訪(fǎng)問(wèn)
header('Access-Control-Allow-Credentials: true');
// 響應(yīng)頭設(shè)置
header('Access-Control-Allow-Headers:x-requested-with,Content-Type,X-CSRF-Token');
}






