日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Web学习之跨域问题及解决方案

發布時間:2023/12/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Web学习之跨域问题及解决方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Web學習之跨域問題及解決方案

javascript/jquery

瀏覽數:161

2017-5-8

在做前端開發時,我們時常使用ajax與服務器通信獲取資源,享受ajax便利的同時,也知道它有限制:跨域安全限制,即同源策略。

同源策略(SOP),核心是確保不同源提供的文件之間是相互獨立的
默認情況下,XHR對象只能訪問與包含它的頁面處于同一域中的資源,這種限制可以預防某些惡意攻擊,但同時也帶來很多不便。

本篇對于常見的解決瀏覽器跨域問題的方案進行總結闡述。

常見解決跨域問題的方案

在web開方中,解決跨域問題最常見的方法有:

  • document.domain+iframe(子域名代理)
  • jsonp實現跨域
  • CORS跨域資源共享
  • postMessage實現跨域

接下來對以上常用方式進行詳細闡述:

document.domain + iframe(子域名代理)

對于主域相同而子域不同的情況,可以通過設置document.domain的辦法來解決。如:對于兩個文件http://www.a.com/a.html和http://blog.a.com/b.html均加上設置document.domain = ‘a.com’;然后在a.html文件中創建一個iframe,通過iframe兩個js文件即可交互數據:

//www.a.com/a.html ????<script> ????????document.doamin = 'a.com'; ????????var iframe = document.createElement('iframe'); ????????iframe.src = 'http://blog.a.com/b.html'; ????????document.body.appendChild(iframe); ????????iframe.onload = function() { ????????????var doc = iframe.contentDocument || iframe.contentWindow.document; ????????????// 在這里操縱b.html ????????????console.log(doc); ????????}; ????</script>

在blog.a.com/b.html內編寫代碼:

//blog.a.com/b.html ????<script> ????????document.domain = 'a.com'; ????</script>

備注:某一頁面的domain默認等于window.location.hostname。主域名是不帶www的域名,例如a.com,主域名前
面帶前綴的通常都為二級域名或多級域名,例如blog.a.com其實是二級域名。 domain只能設置為主域名,不可以在
blog.a.com中將domain設置為test.a.com。

問題:
1、安全性,當一個站點(b.a.com)被攻擊后,另一個站點(c.a.com)會引起安全漏洞。
2、如果一個頁面中引入多個iframe,要想能夠操作所有iframe,必須都得設置相同domain。

jsonp實現跨域

JSONP,即帶填充的JSON,可以在JavaScript中繞過同源策略,發起跨域HTTP請求。
JSONP,一個無關標準,使用腳本標簽來跨域獲取數據的技術。
同源策略有一個顯著例外:HTML腳本元素是可以規避SOP檢查的。這意味著我們可以通過加載外部JavaScript文件的方式來向其他源發出HTTP請求。

<script>http://blog-resource.bj.bcebos.com/files/2016/03/info.js</script>
//http://blog-resource.bj.bcebos.com/files/2016/03/info.js ???var jsonpData = { ???????name: 'jsonp', ???????title: 'JSONP data' ???};

動態的回調函數

JSONP通過script元素加載JSON,通過腳本URL的查詢字符串,服務器將響應封裝在回調函數中,而回調函數名由請求者在URL查詢字符串中給出,此回調函數,即填充。填充可以是任何有效的JavaScript表達式,最常見的是變量和回調函數。

<script> ????????var jsonpCallback = function(data) { ????????????console.log('The response data: ' + JSON.stringify(data)); ????????}; ????????var script = document.createElement('script'); ????????script.async = true; ????????script.src = 'http://blog-resource.bj.bcebos.com/files/2016/03/info2.js?callback=jsonpCallback'; ????????document.body.appendChild(script); ????</script>

在全局作用域下定義回調函數,當HTML DOM中加入script標簽時發起請求,服務端可以通過URL獲取回調函數名,并生成返回如下類似內容:

jsonpCallback({ ???????name: 'jsonp', ???????title: 'JSONP data' ???});

如php實現:

<!--?php ??????header("Content-type: application/javascript"); ??????$callback = $_GET['callback']; ??????$data = json_encode(array( ??????????'name' =--> 'jsonp, ??????????'title' => 'JSONP data' ??????), JSON_PRETTY_PRINT); ??????echo "$callback($data);"; ???>

jQuery利用jsonp發送跨域請求:

$.ajax({??? ??????????url: '',? // 跨域URL?? ??????????type: 'GET',??? ??????????dataType: 'jsonp',??? ??????????jsonp: 'jsonpcallback', //默認callback?? ??????????data: mydata, //請求數據?? ??????????timeout: 5000, ??????????success: function (json) { //客戶端jquery預先定義好的callback函數,成功獲取跨域服務器上的 ???json數據后,會動態執行這個callback函數??? ??????????????if(json.actionErrors.length!=0){??? ??????????????????alert(json.actionErrors);??? ??????????????}??? ??????????},??? ??????????complete: function(XMLHttpRequest, textStatus){??? ??????????} ??????});

JSONP可以說是最簡單的解決跨域請求的方案,但JSONP只支持GET請求,且所能攜帶信息量有限,對于需要使用POST等請求方法或數據量比較大的時候就不適合使用JSONP。

跨域資源共享(CORS)

跨域資源共享(CORS)定義了瀏覽器和服務器如何通過可控方式進行跨域通信。CORS通過添加特殊HTTP頭信息以允許瀏覽器和服務器判斷請求是成功還是失敗。幾乎所有現代瀏覽器都支持CORS。

HTTP請求
當跨域發送HTTP請求時,支持CORS的瀏覽器會通過,添加額外Origin頭信息指定請求源,其值包括請求協議、域名、端口。如:

Origin: http://www.codingplayboy.com

若請求頭中無Origin信息,服務器將不返回任何CORS頭信息。

服務端接收到請求時會檢查頭信息確定是否接受請求:若接受請 求,必須返回一個包含Access-Control-Allow-Origin響應頭,其值與請求頭Origin值相同,如:

Access-Control-Allow-Origin: http://www.codingplayboy.com

對于公共資源且允許任何源請求數據,服務器通常返回該值為通配符*,如:

Access-Control-Allow-Origin: *

瀏覽器接收到服務器HTTP響應時,首先會檢查Access-Control-Allow-Origin的值,只有當值存在且同Origin匹配,才繼續處理該請求。

下面是一段使用CORS跨域請求的代碼:

function createCORS(url, method) { ????if (typeof XMLHttpRequest === 'undefined') { ????????return null; ????} ????//標準瀏覽器 ????var xhr = new XMLHttpRequest(); ????if ('withCredentials' in xhr) { ????????xhr.open(method, url, true); ????}else if (typeof XDomainRequest !== 'undefined') { ????????//IE ????????xhr = new XDomainRequest(); ????????xhr.open(method, null); ????}else { ????????//不支持CORS ????????xhr = null; ????} ????return xhr; } var req = createCORS('http://blog.codingplayboy.com', 'GET'); if (req) { ????req.onload = function() { ????}; ????req.send(); }

Cookie及HTTP認證頭
我們還需要知道不同于普通的HTTP請求,使用CORS發送請求時,默認情況下,瀏覽器不會攜帶任何Cookie和HTTP認證頭等識別信息,只有當我們將XMLHttpRequest對象的withCredentials屬性值設為true,才在該請求發送時添加額外識別信息。

var xhr = new XMLHttpRequest(); xhr.withCredentials = true;

若服務器需要識別信息,則在響應頭中添加Access-Control-Allow-Credentials響應頭:

Access-Control-Allow-Credentials: true

若發送請求時將withCredentials設為true,服務端沒有返回該響應頭,瀏覽器將拒絕該響應。

本來一切都是美好的,然而XDomainRequest不支持withCredentials屬性,于是IE8、IE9并不支持請求時包含識別信息。

預檢請求
使用CORS時,若請求方法不是GET,POST或HEAD,又或者使用了自定義HTTP頭,瀏覽器將發起預檢請求。

預檢請求是一個服務端認證機制,在執行請求之前會判斷該請求是否合法。
發送復雜請求時,瀏覽器會將原始請求的方法和請求頭作為預檢請求的信息發送給服務器;服務器需要決定是否接受該請求并響應,預檢請求通常是使用一種OPTIONS的HTTP方法。

客戶端發起復雜請求時,會先發起預檢,攜帶以下頭信息:

請求頭 描述
Origin 請求源
Access-Control-Request-Method 請求方法(HTTP方法)
Access-Control-Request-Headers 請求自定義頭(以逗號分隔)

服務器返回的響應頭:

響應頭 描述
Access-Control-Allow-Origin 允許的請求源(與請求頭Origin匹配)
Access-Control-Allow-Methods 允許的請求方法(以逗號分隔)
Access-Control-Allow-Headers 允許的頭信息(以逗號分隔)
Access-Control-Max-Age 預檢請求的緩存時間(單位:秒)
Access-Control-Allow-Credentials 指定請求是否支持認證信息(可選)

客戶端接收到服務端的響應后,會使用之前聲明的HTTP方法和請求頭發送真正的請求。

預檢請求會被瀏覽器緩存,緩存時間為Access-Control-Max-Age值,緩存時間內,后續相同類型的請求不再發起重復的預檢請求。IE8、IE9均不支持預檢請求。

HTML5 postMessage

HTML5的window.postMessage為瀏覽器帶來了一個安全的、基于事件的消息API。與之前的子域名代理通過iframe跨子域通信不同,使用postMessage不再是直接訪問一個文檔的屬性和方法,而是向文檔發送消息然后等待響應,這要求形成一條雙向的通信通道。

原文鏈接:http://blog.codingplayboy.com/2016/03/05/web_cross_origin/

總結

以上是生活随笔為你收集整理的Web学习之跨域问题及解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。