ajax處理跨域有幾種方式

1、什麼是跨域

同源策略是由Netscape提出的著名安全策略,是瀏覽器最核心、基本的安全功能,它限制了一個源(origin)中加載文本或者腳本與來自其餘源(origin)中資源的交互方式
,所謂的同源就是指協議、域名、端口相同。
當瀏覽器執行一個腳本時會檢查是否同源,只有同源的腳本纔會執行,若是不一樣源即爲跨域

 2、出現跨域問題的狀況

因爲在工做中須要使用AJAX請求其餘域名下的請求,可是會出現拒絕訪問的狀況,這是由於基於安全的考慮,AJAX只能訪問本地的資源,而不能跨域訪問。javascript

好比說你的網站域名是aaa.com,想要經過AJAX請求bbb.com域名中的內容,瀏覽器就會認爲是不安全的,因此拒絕訪問。php

會出現跨域問題的幾種狀況:html

 

探討跨域請求資源的幾種方式

4、處理跨域的方法2 -- JSONP

 原理
        其本質是利用了標籤<img>||<script>具備可跨域的特性, 由服務端返回一個預先定義好的Javascript函數的調用,而且將服務器數據以該函數參數的形式傳遞過來, 此方法須要先後端配合完成。可是JSONP只支持 「GET」 請求,但不支持 「POST」 請求。前端

服務端JSONP格式數據

jsonp.php 文件代碼

<?php
header('Content-type: application/json');
//獲取回調函數名
$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);
//json數據
$json_data = '["customername1","customername2"]';
//輸出jsonp格式的數據
echo $jsoncallback . "(" . $json_data . ")";
?>java

 

客戶端頁面完整代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 實例</title>
</head>
<body>
    <div id="divCustomers"></div>
    <script type="text/javascript">
function callbackFunction(result, methodName)
        {
            var html = '<ul>';
            for(var i = 0; i < result.length; i++)
            {
                html += '<li>' + result[i] + '</li>';
            }
            html += '</ul>';
            document.getElementById('divCustomers').innerHTML = html;
        }
</script>
<script type="text/javascript" src="http://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction"></script>
</body>
</html>node

 
jQuery 使用 JSONP

 

缺點:

  一、這種方式沒法發送post請求(這裏jquery

  二、另外要肯定jsonp的請求是否失敗並不容易,大多數框架的實現都是結合超時時間來斷定。web

跨域的幾種方式

在項目中可能會須要在一個域名下請求另一個域名的資源,下面咱們來探討下跨域的幾種實現方式ajax

一、jsonp

最多見的一種跨域方式,其背後原理就是利用了script標籤不受同源策略的限制,在頁面中動態插入了script,script標籤的src屬性就是後端api接口的地址,而且以get的方式將前端回調處理函數名稱告訴後端,後端在響應請求時會將回調返還,而且將數據以參數的形式傳遞回去。json

前端:

//http://127.0.0.1:8888/jsonp.html var script = document.createElement('script'); script.src = 'http://127.0.0.1:2333/jsonpHandler?callback=_callback' document.body.appendChild(script); //插入script標籤 //回調處理函數 _callback var _callback = function(obj){ for(key in obj){ console.log('key: ' + key +' value: ' + obj[key]); } }

後端:

//http://127.0.0.1:2333/jsonpHandler app.get('/jsonpHandler', (req,res) => { let callback = req.query.callback; let obj = { type : 'jsonp', name : 'weapon-x' }; res.writeHead(200, {"Content-Type": "text/javascript"}); res.end(callback + '(' + JSON.stringify(obj) + ')'); })

在jsonp.html中打開控制檯能夠看到返回數據的輸出:


jsonp.png

二、CORS

Cross-Origin Resource Sharing(跨域資源共享)是一種容許當前域(origin)的資源(好比html/js/web service)被其餘域(origin)的腳本請求訪問的機制。
當使用XMLHttpRequest發送請求時,瀏覽器若是發現違反了同源策略就會自動加上一個請求頭:origin,後端在接受到請求後肯定響應後會在Response Headers中加入一個屬性:Access-Control-Allow-Origin,值就是發起請求的源地址(http://127.0.0.1:8888),瀏覽器獲得響應會進行判斷Access-Control-Allow-Origin的值是否和當前的地址相同,只有匹配成功後才進行響應處理。

現代瀏覽器中和移動端都支持CORS(除了opera mini),IE下須要8+

前端:

//http://127.0.0.1:8888/cors.html var xhr = new XMLHttpRequest(); xhr.onload = function(data){ var _data = JSON.parse(data.target.responseText) for(key in _data){ console.log('key: ' + key +' value: ' + _data[key]); } }; xhr.open('POST','http://127.0.0.1:2333/cors',true); xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); xhr.send();

後端:

//http://127.0.0.1:2333/cors app.post('/cors',(req,res) => { if(req.headers.origin){ res.writeHead(200,{ "Content-Type": "text/html; charset=UTF-8", "Access-Control-Allow-Origin":'http://127.0.0.1:8888' }); let people = { type : 'cors', name : 'weapon-x' } res.end(JSON.stringify(people)); } })

能夠在開發者工具裏面看到請求的詳細信息,而且在控制檯也能夠看到返回的數據輸出:


response header.png

cors console.png

三、服務器跨域

在先後端分離的項目中能夠藉助服務器實現跨域,具體作法是:前端向本地服務器發送請求,本地服務器代替前端再向api服務器接口發送請求進行服務器間通訊,本地服務器其實就是個中轉站的角色,再將響應的數據返回給前端,下面用node.js作一個示例

前端:

//http://127.0.0.1:8888/server var xhr = new XMLHttpRequest(); xhr.onload = function(data){ var _data = JSON.parse(data.target.responseText) for(key in _data){ console.log('key: ' + key +' value: ' + _data[key]); } }; xhr.open('POST','http://127.0.0.1:8888/feXhr',true); //向本地服務器發送請求 xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); xhr.send("url=http://127.0.0.1:2333/beXhr"); //以參數形式告知須要請求的後端接口

後端:

//http://127.0.0.1:8888/feXhr app.post('/feXhr',(req,res) => { let url = req.body.url; superagent.get(url) //使用superagent想api接口發送請求 .end(function (err,docs) { if(err){ console.log(err); return } res.end(docs.res.text); //返回到前端 }) }) //http://127.0.0.1:2333/beXhr app.get('/beXhr',(req,res) => { let obj = { type : 'superagent', name : 'weapon-x' }; res.writeHead(200, {"Content-Type": "text/javascript"}); res.end(JSON.stringify(obj)); //響應 })

回到 http://127.0.0.1:8888/server 頁面打開控制檯能夠看到數據輸出:

 

 

5、處理跨域的方法3 -- XHR2

「XHR2」 全稱 「XMLHttpRequest Level2」 是HTML5提供的方法,對跨域訪問提供了很好的支持,而且還有一些新的功能。

* IE10如下的版本都不支持

* 只須要在服務器端頭部加上下面兩句代碼:

header( "Access-Control-Allow-Origin:*" );

header( "Access-Control-Allow-Methods:POST,GET" );

相關文章
相關標籤/搜索