成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

前端跨域的處理

ixlei / 2871人閱讀

摘要:由于瀏覽器的同源策略保護(hù)機(jī)制,瀏覽器不能執(zhí)行來(lái)自其他來(lái)源的腳本。然后想要得到所獲取到的數(shù)據(jù),也就是想要得到的的值,還必須把這個(gè)的設(shè)成跟頁(yè)面同一個(gè)域才行,不然根據(jù)前面講的同源策略,是不能訪問(wèn)到里的屬性的。

由于瀏覽器的同源策略保護(hù)機(jī)制,瀏覽器不能執(zhí)行來(lái)自其他來(lái)源的腳本。通過(guò) js 在不同的域之間進(jìn)行數(shù)據(jù)傳輸或通信,比如用 ajax 向一個(gè)不同的域請(qǐng)求數(shù)據(jù),或者通過(guò) js 獲取頁(yè)面中不同域的框架中(iframe)的數(shù)據(jù)的操作就叫跨域。

所謂同源,就是指協(xié)議、域名(IP)、端口三者都相同。只要有其中一者不相同,都是跨域,無(wú)法進(jìn)行數(shù)據(jù)的交流。例如:

注意的是,localhost 與 本機(jī)的 IP 地址也屬于跨域。

瀏覽器執(zhí)行 javascript 腳本時(shí),會(huì)檢查這個(gè)腳本屬于哪個(gè)頁(yè)面,如果不是同源頁(yè)面,就不會(huì)被執(zhí)行。

解決跨域的方法

解決方法主要有以下幾種:

方法一:設(shè)置 webpack 的服務(wù)器代理

1、在工程化的前端項(xiàng)目中,在本機(jī)進(jìn)行開(kāi)發(fā)時(shí),后臺(tái)的接口可能會(huì)出現(xiàn)跨域,可以設(shè)置 webpack 的服務(wù)器代理,將本機(jī)的請(qǐng)求轉(zhuǎn)發(fā)到與接口同源的地址。

首先安裝插件:webpack-dev-server,然后再 config 文件夾里找到 index.js 文件,在 dev 對(duì)象下的 proxyTable 字段添加對(duì)應(yīng)的需要替換的地址。

module.exports = {

  ...

  devServer: {   //本地開(kāi)發(fā)服務(wù)器設(shè)置

    ...

    port: 8080,     //當(dāng)前的端口號(hào)

    proxyTable: {  //服務(wù)器代理設(shè)置

      "/v3/admin": {  //需要代理的接口形式

        target: "http://localhost:8700",  //將當(dāng)前端口號(hào)代理到8700

        changeOrigin: true,

        secure: false

      }

    }

  }

}

以上設(shè)置就是將所有包含 "/v3/admin" 字段的接口,從原來(lái)的 localhost: 8080 代理到 localhost: 8700 ,變成 "http://localhost: 8700/v3/admin" 從而獲取到 8700 端口的內(nèi)容。

方法二:使用 CORS 進(jìn)行數(shù)據(jù)傳輸

CORS是一個(gè)W3C標(biāo)準(zhǔn),全稱是"跨域資源共享"(Cross-origin resource sharing)。

它允許瀏覽器向跨源服務(wù)器,發(fā)出 XMLHttpRequest 請(qǐng)求,從而克服了 AJAX 只能同源使用的限制。

CORS 標(biāo)準(zhǔn)新增了一組 HTTP 首部字段,允許服務(wù)器聲明哪些源站有權(quán)限訪問(wèn)哪些資源。另外,規(guī)范要求,對(duì)那些可能對(duì)服務(wù)器數(shù)據(jù)產(chǎn)生副作用的 HTTP 請(qǐng)求方法(特別是 GET 以外的 HTTP 請(qǐng)求,或者搭配某些 MIME 類型的 POST 請(qǐng)求),瀏覽器必須首先使用 OPTIONS 方法發(fā)起一個(gè)預(yù)檢請(qǐng)求(preflight request),從而獲知服務(wù)端是否允許該跨域請(qǐng)求。服務(wù)器確認(rèn)允許之后,才發(fā)起實(shí)際的 HTTP 請(qǐng)求。在預(yù)檢請(qǐng)求的返回中,服務(wù)器端也可以通知客戶端,是否需要攜帶身份憑證(包括 Cookies和 HTTP 認(rèn)證相關(guān)數(shù)據(jù))。

CORS需要瀏覽器和服務(wù)器同時(shí)支持,瀏覽器需要 ie8 以上。

瀏覽器端的寫(xiě)法:

    function CORSRequest(method,url,opation,callback) {
    
      var xhr = new XMLHttpRequest();
    
      if ("withCredentials" in xhr) {
    
        // 此時(shí)即支持CORS的情況
    
        // 檢查XMLHttpRequest對(duì)象是否有“withCredentials”屬性
    
        // “withCredentials”僅存在于XMLHTTPRequest level 2對(duì)象里
    
      } else {
    
        // 否則檢查是否支持XDomainRequest
    
        // XDomainRequest僅存在于IE中,是IE8 和 IE9 用于支持CORS請(qǐng)求的方式
    
        xhr = new XDomainRequest();
    
      }
    
      xhr.open(method, url, true);
    
      if(method=="POST"){  //可以設(shè)置不同請(qǐng)求方法的操作,所有的請(qǐng)求都可以分別設(shè)置
    
        xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");  //設(shè)置請(qǐng)求頭
    
        xhr.send(opation);  //傳輸數(shù)據(jù)到服務(wù)器
    
      }else{
    
        xhr.send();
    
      }
    
      xhr.onload = function(){
    
        callback(xhr.responseText);
    
      }
    
    };
    
    function notice(data) {
    
      console.log(data)
    
    }
    
    CORSRequest("POST","http://example.com","傳遞給服務(wù)器的數(shù)據(jù)",notice);

服務(wù)器端的寫(xiě)法:

Apache:

Apache需要使用 mod_headers 模塊來(lái)激活 HTTP 頭的設(shè)置,它默認(rèn)是激活的。你只需要在 Apache 配置文件的, , 或的配置里加入以下內(nèi)容即可:

    Header set Access-Control-Allow-Origin *  

PHP:

    

以上的配置的含義是允許任何域發(fā)起的請(qǐng)求都可以獲取當(dāng)前服務(wù)器的數(shù)據(jù)。當(dāng)然,這樣有很大的危險(xiǎn)性,惡意站點(diǎn)可能通過(guò)XSS攻擊我們的服務(wù)器。所以我們應(yīng)該盡量有針對(duì)性的對(duì)限制安全的來(lái)源,例如:

    ?

CORS 的優(yōu)點(diǎn):

CORS與JSONP相比,無(wú)疑更為先進(jìn)、方便和可靠。

JSONP 只能實(shí)現(xiàn) GET 請(qǐng)求,而 CORS 支持所有類型的HTTP請(qǐng)求。

使用 CORS,開(kāi)發(fā)者可以使用普通的 XMLHttpRequest 發(fā)起請(qǐng)求和獲得數(shù)據(jù),擁有onerror 和 onabort 方法,比起 JSONP 有更好的錯(cuò)誤處理。

JSONP 主要被老的瀏覽器支持,它們往往不支持 CORS,而絕大多數(shù)現(xiàn)代瀏覽器都已經(jīng)支持了 CORS。

注意點(diǎn):

當(dāng)發(fā)送的請(qǐng)求是非簡(jiǎn)單請(qǐng)求,瀏覽器會(huì)在正式通信之前,增加一次 HTTP 查詢請(qǐng)求,稱為"預(yù)檢"請(qǐng)求( preflight )。瀏覽器先詢問(wèn)服務(wù)器,當(dāng)前網(wǎng)頁(yè)所在的域名是否在服務(wù)器的許可名單之中,以及可以使用哪些 HTTP 動(dòng)詞和頭信息字段。只有得到肯定答復(fù),瀏覽器才會(huì)發(fā)出正式的 XMLHttpRequest 請(qǐng)求,否則就報(bào)錯(cuò)。

一般前端框架比如"ExtJS"、"AngularJS", 框架監(jiān)測(cè)到訪問(wèn)的域名可能存在跨域的話會(huì)先發(fā)送一個(gè) OPTIONS 請(qǐng)求,驗(yàn)證是否可進(jìn)行通信,如果返回可通信才會(huì)真正發(fā)起一個(gè) POST、GET 請(qǐng)求。

下圖是框架發(fā)起的 OPTIONS 請(qǐng)求,當(dāng)如果服務(wù)器的 Nginx 并沒(méi)有設(shè)置允許跨域請(qǐng)示的時(shí)候,它會(huì)返回一個(gè) 405 狀態(tài)碼。

axios 框架也會(huì)發(fā)送 OPTIONS 請(qǐng)求。

關(guān)于 CROS 的更多內(nèi)容,可以進(jìn)入以下鏈接了解:

https://developer.mozilla.org...

http://www.ruanyifeng.com/blo...

方法三:JSONP

在 js 中,我們直接用 XMLHttpRequest 請(qǐng)求不同域上的數(shù)據(jù)時(shí),是不可以的。但是,在頁(yè)面上引入不同域上的 js 腳本文件卻是可以的,jsonp 正是利用這個(gè)特性來(lái)實(shí)現(xiàn)的。

JSONP是一種非正式傳輸協(xié)議,該協(xié)議的一個(gè)要點(diǎn)就是允許用戶傳遞一個(gè)約定的參數(shù)(一般是 callback )給服務(wù)端,然后服務(wù)端返回?cái)?shù)據(jù)時(shí)會(huì)將這個(gè) callback 參數(shù)作為函數(shù)名來(lái)包裹住JSON數(shù)據(jù),這樣客戶端就可以隨意定制自己的函數(shù)來(lái)自動(dòng)處理返回?cái)?shù)據(jù)了。

比如,有個(gè) a.html 頁(yè)面,它里面的代碼需要利用 ajax 獲取一個(gè)不同域上的 json 數(shù)據(jù),假設(shè)這個(gè) json 數(shù)據(jù)地址是 http://example.com/data.php , 那么 a.html 中的代碼就可以這樣:

我們看到獲取數(shù)據(jù)的地址后面還有一個(gè) callback 參數(shù),按慣例是用這個(gè)參數(shù)名,但是你用其他的也一樣。當(dāng)然如果獲取數(shù)據(jù)的jsonp地址頁(yè)面不是你自己能控制的,就得按照提供數(shù)據(jù)的那一方的規(guī)定格式來(lái)操作了。關(guān)鍵是參數(shù)值必須是當(dāng)前頁(yè)面 script 設(shè)置的數(shù)據(jù)處理回調(diào)函數(shù)的名字。

因?yàn)槭钱?dāng)做一個(gè)js文件來(lái)引入的,所以http://example.com/data.php 返回的必須是一個(gè)能執(zhí)行的js文件,所以這個(gè)頁(yè)面的php代碼可能是這樣的:

最終那個(gè)頁(yè)面輸出的結(jié)果是:

所以通過(guò) http://example.com/data.php?c... 得到的 js 文件,就是我們之前定義的 dosomething 函數(shù),并且它的參數(shù)就是我們需要的 json 數(shù)據(jù),這樣我們就跨域獲得了我們需要的數(shù)據(jù)。

這樣 jsonp 的原理就很清楚了,通過(guò) script 標(biāo)簽引入一個(gè) js 文件,這個(gè) js 文件載入成功后會(huì)執(zhí)行我們?cè)?url 參數(shù)中指定的函數(shù),并且會(huì)把我們需要的 json 數(shù)據(jù)作為參數(shù)傳入。所以 jsonp 是需要服務(wù)器端的頁(yè)面進(jìn)行相應(yīng)的配合的。

知道 jsonp 跨域的原理后我們就可以用 js 動(dòng)態(tài)生成 script 標(biāo)簽來(lái)進(jìn)行跨域操作了,而不用特意的手動(dòng)的書(shū)寫(xiě)那些 script 標(biāo)簽。

一個(gè)跨域獲取淘寶關(guān)鍵字搜索建議的例子:

效果:

優(yōu)點(diǎn):

不受同源策略的限制;

兼容性更好,在更加古老的瀏覽器中都可以運(yùn)行,不需要XMLHttpRequest或ActiveX的支持;

請(qǐng)求完畢后可以通過(guò)調(diào)用callback的方式回傳結(jié)果。

缺點(diǎn):

只支持GET請(qǐng)求而不支持POST等其它類型的HTTP請(qǐng)求;

只支持跨域HTTP請(qǐng)求這種情況,不能解決不同域的兩個(gè)頁(yè)面之間如何進(jìn)行JavaScript調(diào)用的問(wèn)題。

方法四:設(shè)置代理服務(wù)器

例如 www.123.com/index.html 需要調(diào)用 www.456.com/server.php,可以寫(xiě)一個(gè)接口 www.123.com/server.php ,由這個(gè)接口在后端去調(diào)用 www.456.com/server.php 并拿到返回值,然后再返回給 index.html,這就是一個(gè)代理的模式。相當(dāng)于繞過(guò)了瀏覽器端,自然就不存在跨域問(wèn)題。

例如:

a.php 后臺(tái)獲取跨域的數(shù)據(jù)

    ?

前端只要將 XMLHttpRequest 的請(qǐng)求地址設(shè)置為 "a.php" 就可以。

方法五:使用 window.name

window 對(duì)象有個(gè) name 屬性,該屬性有個(gè)特征:即在一個(gè)窗口( window )的生命周期內(nèi),窗口載入的所有的頁(yè)面都是共享一個(gè) window.name 的,每個(gè)頁(yè)面對(duì) window.name 都有讀寫(xiě)的權(quán)限,window.name 是持久存在一個(gè)窗口載入過(guò)的所有頁(yè)面中的,并不會(huì)因新頁(yè)面的載入而進(jìn)行重置。

比如:有一個(gè)頁(yè)面 a.html,它里面有這樣的代碼:

再看看 b.html 頁(yè)面的代碼:

a.html 頁(yè)面載入后 3 秒,跳轉(zhuǎn)到了 b.html 頁(yè)面,結(jié)果為:

我們看到在 b.html 頁(yè)面上成功獲取到了它的上一個(gè)頁(yè)面 a.html 給 window.name 設(shè)置的值。如果在之后所有載入的頁(yè)面都沒(méi)對(duì) window.name 進(jìn)行修改的話,那么所有這些頁(yè)面獲取到的 window.name 的值都是 a.html 頁(yè)面設(shè)置的那個(gè)值。當(dāng)然,如果有需要,其中的任何一個(gè)頁(yè)面都可以對(duì) window.name 的值進(jìn)行修改。注意,window.name 的值只能是字符串的形式,這個(gè)字符串的大小最大能允許 2M 左右甚至更大的一個(gè)容量,具體取決于不同的瀏覽器,但一般是夠用了。

上面的例子中,我們用到的頁(yè)面 a.html 和 b.html 是處于同一個(gè)域的,但是即使 a.html 與 b.html 處于不同的域中,上述結(jié)論同樣是適用的,這也正是利用 window.name 進(jìn)行跨域的原理。

此方法需要與 iframe 配合使用。

比如有一個(gè) www.example.com/a.html 頁(yè)面,需要通過(guò) a.html 頁(yè)面里的 js 來(lái)獲取另一個(gè)位于不同域上的頁(yè)面 www.cnblogs.com/data.html 里的數(shù)據(jù)。

data.html 頁(yè)面里的代碼很簡(jiǎn)單,就是給當(dāng)前的 window.name 設(shè)置一個(gè) a.html 頁(yè)面想要得到的數(shù)據(jù)值。data.html 里的代碼:

那么在 a.html 頁(yè)面中,我們?cè)趺窗?data.html 頁(yè)面載入進(jìn)來(lái)呢?顯然我們不能直接在 a.html 頁(yè)面中通過(guò)改變 window.location 來(lái)載入 data.html 頁(yè)面,因?yàn)槲覀兿胍词?a.html 頁(yè)面不跳轉(zhuǎn)也能得到 data.html 里的數(shù)據(jù)。答案就是在 a.html 頁(yè)面中使用一個(gè)隱藏的 iframe 來(lái)充當(dāng)一個(gè)中間人角色,由 iframe 去獲取 data.html 的數(shù)據(jù),然后 a.html 再去得到iframe獲取到的數(shù)據(jù)。

充當(dāng)中間人的 iframe 想要獲取到 data.html 的通過(guò) window.name 設(shè)置的數(shù)據(jù),只需要把這個(gè) iframe 的 src 設(shè)為 www.cnblogs.com/data.html 就行了。然后 a.html 想要得到 iframe 所獲取到的數(shù)據(jù),也就是想要得到 iframe的window.name 的值,還必須把這個(gè) iframe 的 src 設(shè)成跟 a.html 頁(yè)面同一個(gè)域才行,不然根據(jù)前面講的同源策略,a.html 是不能訪問(wèn)到 iframe 里的 window.name 屬性的。這就是整個(gè)跨域過(guò)程。

看下 a.html 頁(yè)面的代碼:

上面的代碼只是最簡(jiǎn)單的原理演示代碼,你可以對(duì)使用 js 封裝上面的過(guò)程,比如動(dòng)態(tài)的創(chuàng)建 iframe ,動(dòng)態(tài)的注冊(cè)各種事件等等,當(dāng)然為了安全,獲取完數(shù)據(jù)后,還可以銷毀作為代理的 iframe。

方法六:使用 window.postMessage

window.postMessage(message,targetOrigin) 方法是 html5 新引進(jìn)的特性,可以使用它來(lái)向其它的 window 對(duì)象發(fā)送消息,無(wú)論這個(gè) window 對(duì)象是屬于同源或不同源,目前 IE8+、FireFox、Chrome、Opera 等瀏覽器都已經(jīng)支持 window.postMessage 方法。

調(diào)用 postMessage 方法的 window 對(duì)象是指要接收消息的那一個(gè) window 對(duì)象,該方法的第一個(gè)參數(shù) message 為要發(fā)送的消息,類型只能為字符串;第二個(gè)參數(shù) targetOrigin 用來(lái)限定接收消息的那個(gè) window 對(duì)象所在的域,如果不想限定域,可以使用通配符 * 。

需要接收消息的 window對(duì) 象,可是通過(guò)監(jiān)聽(tīng)自身的 message 事件來(lái)獲取傳過(guò)來(lái)的消息,消息內(nèi)容儲(chǔ)存在該事件對(duì)象的 data 屬性中。

上面所說(shuō)的向其他 window 對(duì)象發(fā)送消息,其實(shí)就是指一個(gè)頁(yè)面有幾個(gè)框架的那種情況,因?yàn)槊恳粋€(gè)框架都有一個(gè) window 對(duì)象。下面看一個(gè)簡(jiǎn)單的示例,有兩個(gè)頁(yè)面

我們運(yùn)行 a 頁(yè)面后得到的結(jié)果:

我們看到 b 頁(yè)面成功的收到了消息。

使用 postMessage 來(lái)跨域傳送數(shù)據(jù)還是比較直觀和方便的,但是缺點(diǎn)是 IE6、IE7 不支持,所以用不用還得根據(jù)實(shí)際需要來(lái)決定。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/90292.html

相關(guān)文章

  • 前端域的處理

    摘要:由于瀏覽器的同源策略保護(hù)機(jī)制,瀏覽器不能執(zhí)行來(lái)自其他來(lái)源的腳本。然后想要得到所獲取到的數(shù)據(jù),也就是想要得到的的值,還必須把這個(gè)的設(shè)成跟頁(yè)面同一個(gè)域才行,不然根據(jù)前面講的同源策略,是不能訪問(wèn)到里的屬性的。 由于瀏覽器的同源策略保護(hù)機(jī)制,瀏覽器不能執(zhí)行來(lái)自其他來(lái)源的腳本。通過(guò) js 在不同的域之間進(jìn)行數(shù)據(jù)傳輸或通信,比如用 ajax 向一個(gè)不同的域請(qǐng)求數(shù)據(jù),或者通過(guò) js 獲取頁(yè)面中不同域...

    wthee 評(píng)論0 收藏0
  • 跨域域的簡(jiǎn)易實(shí)現(xiàn)和測(cè)試

    摘要:前言由于自己平時(shí)只做做,并沒(méi)有遇到太多跨域問(wèn)題,今天通過(guò)幾個(gè)樣例模擬實(shí)現(xiàn)了幾種跨域方式。 前言 由于自己平時(shí)只做做demo,并沒(méi)有遇到太多跨域問(wèn)題,今天通過(guò)幾個(gè)樣例模擬實(shí)現(xiàn)了幾種跨域方式。原文地址 傳送門(mén) 本文所有樣例靜態(tài)服務(wù)器基于nodejs實(shí)現(xiàn),代碼親測(cè)可用。測(cè)試步驟如下: 1.為了實(shí)現(xiàn)跨域訪問(wèn)的效果,需要下載http-server 作為一個(gè)服務(wù)器 npm install http...

    ninefive 評(píng)論0 收藏0
  • 2018年騰訊前端一面總結(jié)(面向2019屆學(xué)生)

    摘要:前言騰訊一面,相比阿里一面來(lái)說(shuō),騰訊一面先給打電話預(yù)定時(shí)間,這也給了我們這些面試者去準(zhǔn)備的時(shí)間。其實(shí)閉包也就是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域的函數(shù)而已。常用的創(chuàng)建閉包的方法就是在函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。 前言 騰訊一面,相比阿里一面來(lái)說(shuō),騰訊一面先給打電話預(yù)定時(shí)間,這也給了我們這些面試者去準(zhǔn)備的時(shí)間。但是也正是因?yàn)檫@種確定性,也有在等待電話的時(shí)候的心情的忐忑。 背景 我是一名大三學(xué)生,大一...

    Kosmos 評(píng)論0 收藏0
  • 那些年曾談起的跨域

    摘要:在中,在不同的域名下面進(jìn)行數(shù)據(jù)交互,就會(huì)遇到跨域問(wèn)題,說(shuō)到跨域首先要從同源說(shuō)起,瀏覽器為了提供一種安全的運(yùn)行環(huán)境,各個(gè)瀏覽器廠商協(xié)定使用同源策略。在上面說(shuō)過(guò)是不受同源策略限制的,但是出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源請(qǐng)求。 對(duì)于前端開(kāi)發(fā)來(lái)說(shuō)跨域應(yīng)該是最不陌生的問(wèn)題了,無(wú)論是開(kāi)發(fā)過(guò)程中還是在面試過(guò)程中都是一個(gè)經(jīng)常遇到的一個(gè)問(wèn)題,在開(kāi)發(fā)過(guò)程中遇到這個(gè)問(wèn)題的話一般都是找后端同學(xué)去解決...

    galois 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<