Ajax 跨域解決方案
在解決Ajax跨域問題之前,我們先一起來看看什麼是瀏覽器的同源策略
一.瀏覽器同源政策
- 含義
1995年,同源政策由 Netscape 公司引入瀏覽器。目前,所有瀏覽器都實行這個政策。
最初,它的含義是指,A網頁設定的 Cookie,B網頁不能開啟,除非這兩個網頁"同源"。所謂"同源"指的是"三個相同"。
協議相同
域名相同
埠相同
舉例來說,http://www.guangzhou.com/p/page.html這個網址,協議是http://,域名是 www.guangzhou.com,埠是80(預設埠可以省略)。它的同源情況如下。
http://www.guangzhou.com/dir/other.html: 同源
http://guangzhou.com/dir/other.html: 不同源(域名不同)
http://v2.www.guangzhou.com/dir/other.html:不同源(域名不同)
http://www.guangzhou.com:81/dir/other.html:不同源(埠不同)
目的
同源政策的目的,是為了保證使用者資訊的安全,防止惡意的網站竊取資料。
設想這樣一種情況:A網站是一家銀行,使用者登入以後,又去瀏覽其他網站。如果其他網站可以讀取A網站的 Cookie,會發生什麼?
很顯然,如果 Cookie 包含隱私(比如存款總額),這些資訊就會洩漏。更可怕的是,Cookie 往往用來儲存使用者的登入狀態,如果使用者沒有退出登入,其他網站就可以冒充使用者,為所欲為。因為瀏覽器同時還規定,提交表單不受同源政策的限制。
由此可見,"同源政策"是必需的,否則 Cookie 可以共享,網際網路就毫無安全可言了。限制範圍
隨著網際網路的發展,"同源政策"越來越嚴格。目前,如果非同源,共有三種行為受到限制。
(1) Cookie、LocalStorage 和 IndexDB 無法讀取。
(2) DOM 無法獲得。
(3) AJAX 請求不能傳送。
雖然這些限制是必要的,但是有時很不方便,合理的用途也受到影響。
在同源策略下,在某個伺服器下的頁面是無法獲取到該伺服器以外的資料的,但img、iframe、script等標籤是個例外,這些標籤可以通過src屬性請求到其他伺服器上的資料。
我們下面只專注於ajax跨域請求!!!
二.如何解決ajax跨域
一般ajax跨域就是通過代理,JSONP或者CORS三種方式解決(注意,現在JSONP很少用了,所以瞭解下即可)
(1)JSONP方式解決跨域問題
jsonp解決跨域問題是一個比較古老的方案(實際中不推薦使用),這裡做簡單介紹(實際專案中如果要使用JSONP,一般會使用JQ等對JSONP進行了封裝的類庫來進行ajax請求)
實現原理
JSONP之所以能夠用來解決跨域方案,主要是因為 <script> 指令碼擁有跨域能力,而JSONP正是利用這一點來實現。具體原理如圖
實現流程
客戶端網頁網頁通過新增一個<script>元素,向伺服器請求JSON資料,這種做法不受同源政策限制
當我們通過JSONP模式請求跨域資源時,伺服器返回給客戶端一段javascript程式碼,這段javascript程式碼自動呼叫客戶端回撥函式。
客戶端
伺服器端(PHP)
<?php
$staff = array
(
array("name" => "洪七", "number" => "101", "sex" => "男", "job" => "總經理"),
array("name" => "郭靖", "number" => "102", "sex" => "男", "job" => "開發工程師"),
array("name" => "黃蓉", "number" => "103", "sex" => "女", "job" => "產品經理")
);
$jsonp = $_GET["callback"];
//檢查是否有員工編號的引數
if (!isset($_GET["number"]) || empty($_GET["number"])) {
echo $jsonp . '({"success":false,"msg":"引數錯誤"})';
return;
}
//獲取number引數
$number = $_GET["number"];
$result = $jsonp . '({"success":false,"msg":"沒有找到員工。"})';
//遍歷$staff多維陣列,查詢key值為number的員工是否存在,如果存在,則修改返回結果
foreach ($staff as $value) {
if ($value["number"] == $number) {
$result = $jsonp . '({"success":true,"msg":"找到員工:員工編號:' . $value["number"] .
',員工姓名:' . $value["name"] .
',員工性別:' . $value["sex"] .
',員工職位:' . $value["job"] . '"})';
break;
}
}
echo $result;
由於<script>元素請求的指令碼,直接作為程式碼執行。這時,只要瀏覽器定義了foo函式,該函式就會立即呼叫。作為引數的JSON資料被視為JavaScript物件,而不是字串,因此避免了使用JSON.parse的步驟。
注意,一般的JSONP介面和普通介面返回資料是有區別的,所以介面如果要做JSONO相容,需要進行判斷是否有對應callback關鍵字引數,如果有則是JSONP請求,返回JSONP資料,否則返回普通資料
附(JQ對JSONP進行了封裝的類庫來進行ajax請求):
使用注意
基於JSONP的實現原理,所以JSONP只能是“GET”請求,不能進行較為複雜的POST和其它請求,所以遇到那種情況,就得參考下面的CORS解決跨域了(所以如今它也基本被淘汰了)
(2)CORS解決跨域問題
CORS請求原理
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源伺服器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
基本上目前所有的瀏覽器都實現了CORS標準(IE10以下不支援),其實目前幾乎所有的瀏覽器ajax請求都是基於CORS機制的,只不過可能平時前端開發人員並不關心而已(所以說其實現在CORS解決方案主要是考慮後臺該如何實現的問題)。
如何判斷是否是簡單請求?
瀏覽器將CORS請求分成兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。只要同時滿足以下兩大條件,就屬於簡單請求。
請求方法是以下三種方法之一:HEAD,GET,POST
HTTP的頭資訊不超出以下幾種欄位:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type(只限於三個值application/x-www-form-urlencoded、 multipart/form-data、text/plain)
凡是不同時滿足上面兩個條件,就屬於非簡單請求。
實現——PHP後臺配置
PHP後臺的配置幾乎是所有後臺中最為簡單的,遵循如下步驟即可:
第一步:配置Php 後臺允許跨域
<?php
header('Access-Control-Allow-Origin:*'); //支援全域名訪問,不安全,部署後需要固定限制為客戶端網址
header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); //支援的http 動作
header('Access-Control-Allow-Headers:x-requested-with,content-type'); //響應頭 請按照自己需求新增。
實現——Node.js後臺配置(express框架)
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", ' 3.2.1')
//這段僅僅為了方便返回json而已
res.header("Content-Type", "application/json;charset=utf-8");
if(req.method == 'OPTIONS') {
//讓options請求快速返回
res.sendStatus(200);
} else {
next();
}
});
(3)代理請求方式解決跨域問題
這種方式是通過後臺(ASP、PHP、JAVA、ASP.NET)獲取其他域名下的內容,然後再把獲得內容返回到前端,這樣因為在同一個域名下,所以就不會出現跨域的問題。
實現過程
比如在廣州的WEB伺服器的後臺(www.guangzhou.com/proxy-shanghaiservice.php)來呼叫上海(www.shanghai.com/service.php)的服務,然後把響應的結果返回前端,這樣前端呼叫廣州同域名的服務就和呼叫上海的服務效果相同了。
參考資料:
瀏覽器同源政策及其規避方法
相關文章
- ajax跨域的解決方案跨域
- 解決 ajax 跨域跨域
- Ajax 跨域請求 Access to XMLHttpRequest 解決方案跨域XMLHTTP
- 瀏覽器同源策略及 Ajax 跨域解決方案瀏覽器跨域
- 跨域原理以及跨域解決方案跨域
- 解決Ajax不能跨域的方法跨域
- iris 跨域解決方案跨域
- Laravel 跨域解決方案Laravel跨域
- 前端跨域的解決方案前端跨域
- js跨域解決方案(一)JS跨域
- spring mvc解決ajax跨域問題SpringMVC跨域
- 跨域問題,解決方案 – CORS方案跨域CORS
- 跨域問題,解決方案 - CORS方案跨域CORS
- AJAX跨域完全講解跨域
- 跨域多方位解決方案跨域
- 跨域問題及解決方案跨域
- SignalR跨域解決方案全面SignalR跨域
- 跨域解決方案(總結篇)跨域
- 跨域的原因以及解決方案跨域
- 跨域的幾種解決方案跨域
- PHPAjax跨域問題解決方案PHP跨域
- 解決ajax跨域問題的多種方法跨域
- Flutter Web 跨域問題解決方案FlutterWeb跨域
- 常見的跨域解決方案(全)跨域
- Nginx跨域的問題解決方案Nginx跨域
- 前端常見跨域解決方案(全)前端跨域
- 前端跨域問題及其解決方案前端跨域
- nginx /Java 解決跨域問題方案NginxJava跨域
- 簡單的瞭解跨域以及解決方案跨域
- Vue中跨域問題解決方案1Vue跨域
- SpringBoot跨域問題解決方案Spring Boot跨域
- 跨域問題,解決方案 - Nginx反向代理跨域Nginx
- 什麼是跨域?解決方案有哪些?跨域
- WebApi 跨域問題解決方案(3):CORSWebAPI跨域CORS
- AJAX 跨域請求解跨域
- AJAX 跨域問題跨域
- Ajax跨域問題跨域
- ajax jsonp跨域JSON跨域