一文搞懂│什麼是跨域?如何解決跨域?
- 2022 年 7 月 15 日
- 筆記
- 《一文讓你搞懂系列》, 效率提升, 經驗分享, 跨域
🎈 什麼是跨域
- 域: 是指瀏覽器不能執行其他網站的腳本
- 跨域: 它是由瀏覽器的 同源策略 造成的,是瀏覽器對
JavaScript
實施的安全限制,所謂同源(即指在同一個域)就是兩個頁面具有相同的協議protocol
,主機host
和埠號port
則就會造成 跨域
域名組成
🎈 跨域場景
- 場景的跨域場景有哪些,請參考下表
當前url | 請求url | 是否跨域 | 原因 |
---|---|---|---|
//www.autofelix.cn |
//www.autofelix.cn/api.php |
否 | 協議/域名/埠都相同 |
//www.autofelix.cn |
//www.autofelix.cn/api.php |
是 | 協議不同 |
//www.autofelix.cn |
//www.rabbit.cn |
是 | 主域名不同 |
//www.autofelix.cn |
//api.autofelix.cn |
是 | 子域名不同 |
//www.autofelix.cn:80 |
//www.autofelix.cn:8080 |
是 | 埠不同 |
🎈 解決跨域的四種方式
- nginx的反向代理
- 使用
nginx
反向代理實現跨域,是最簡單的跨域方式 - 只需要修改
nginx
的配置即可解決跨域問題,支援所有瀏覽器,支援session
,不需要修改任何程式碼,並且不會影響伺服器性能
// nginx配置
server {
listen 81;
server_name www.domain1.com;
location / {
proxy_pass //www.domain2.com:8080; #反向代理
proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
index index.html index.htm;
# 當用webpack-dev-server等中間件代理介面訪問nignx時,此時無瀏覽器參與,故沒有同源限制,下面的跨域配置可不啟用
add_header Access-Control-Allow-Origin //www.domain1.com; #當前端只跨域不帶cookie時,可為*
add_header Access-Control-Allow-Credentials true;
}
}
- jsonp請求
jsonp
是伺服器與客戶端跨源通訊的常用方法。最大特點就是簡單適用,兼容性好兼容低版本IE
,缺點是只支援get
請求,不支援post
請求- 原理時網頁通過添加一個
<script>
元素,向伺服器請求json
數據,伺服器收到請求後,將數據放在一個指定名字的回調函數的參數位置傳回來
//jquery實現
<script>
$.getJSON('//autofelix.com/api.php&callback=?', function(res) {
// 處理獲得的數據
console.log(res)
});
</script>
- 後端語言代理
- 可以通過一種沒有跨域限制的語言中轉一下,通過後端語言去請求資源,然後再返回數據
- 比如
//www.autofelix.cn
需要調用//api.autofelix.cn/userinfo
去獲取用戶數據,因為子域名不同,會有跨域限制 - 可以先請求
//www.autofelix.cn
下的php
文件,比如//www.autofelix.cn/api.php
,然後再通過該php
文件返回數據
// 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('//api.autofelix.cn/userinfo');
return $result;
- 後端語言的設置
- 主要通過後端語言主動設置跨域請求,這裡以
php
作為案例
// 允許所有域名訪問
header('Access-Control-Allow-Origin: *');
// 允許單個域名訪問
header('Access-Control-Allow-Origin: //autofelix.com');
// 允許多個自定義域名訪問
static public $originarr = [
'//autofelix.com',
'//baidu.com',
'//csdn.net',
];
// 獲取當前跨域域名
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
if (in_array($origin, self::$originarr)) {
// 允許 $originarr 數組內的 域名跨域訪問
header('Access-Control-Allow-Origin:' . $origin);
// 響應類型
header('Access-Control-Allow-Methods:POST,GET');
// 帶 cookie 的跨域訪問
header('Access-Control-Allow-Credentials: true');
// 響應頭設置
header('Access-Control-Allow-Headers:x-requested-with,Content-Type,X-CSRF-Token');
}