跨域與經常使用解決方法

接觸前端有幾個月了,今天說一說我對前端跨域的認識和解決方案,其實在以前我對跨域並無什麼概念
只是聽聞過這個惡名遠揚的單詞,直到有一天我遇到了他
html

什麼是跨域

同源策略限制了從同一個源加載的文檔或腳本如何與來自另外一個源的資源進行交互。這是一個用於隔離潛在惡意文件的重要安全機制。若是兩個頁面的協議,端口(若是有指定)和主機都相同,則兩個頁面具備相同的源。咱們也能夠把它稱爲「協議/主機/端口 tuple」,或簡單地叫作「tuple". ("tuple" ,「元」,是指一些事物組合在一塊兒造成一個總體,好比(1,2)叫二元,(1,2,3)叫三元)。(mdn)前端

上邊這一段話來自於MDN,反正在我看來這麼一大段幹(gou)淨(pi)利(bu)落(tong)的話實在是很官方,html5

說白了跨域就是說 主機名(域名)、協議、端口號只要有其一不一樣,就爲不一樣的域,那麼這個時候你去請求的話就會發生跨域node

總之就是瀏覽器的一種叫作同源策略限制的東西在搞事情json

同源策略限制

大概講的是請求的時候會發送一個Origin報頭到被請求的地址
而後被請求的地址返給請求者一個Access-Control-Allow-Origin響應頭,若是值爲*或者和Origin的站點對應,那麼就能夠請求,若是不對應就會跨域跨域

  • 同源策略限制這個東西我以爲主要就是針對請求,若是沒有的話,假如你進入了一個須要登錄的網站,你登錄完成以後,瀏覽器保存了你的cookie,而後你在不退出的狀況下中途訪問了其餘的惡意網站,這個惡意網站就能夠盜取你的登錄信息去直接登錄你的帳號瀏覽器

  • 還有一種就是這個同源策略限制了dom的查詢好比說咱們項目中用到過iframe 這個標籤 ,他能夠將一個html頁面嵌入到當前的頁面中,若是說一個網站把另外一個你信任的網站經過iframe嵌入到本身的網站的話,那麼你輸入的一切東西都會被人家看的一清二楚,有了同源策略的話通常都須要去代理其餘域名或者加入白名單,才能引入那個域名的html,安全

能夠說是同源策略限制給了用戶一個基本的保護服務器

url的組成(統一資源定位符)

一直以來,自從我接觸前端以來,我就在不停的和url打交道,but我以前都是管這個東西叫域名的,
非常尷尬,
url中文叫作統一資源定位符,是互聯網上一處資源的地址,一個完整的url主要有一下及部分組成微信

  • 協議部分 ,比較常見的有http https ftp 等
  • 域名部分,好比說www.baidu.com 這一塊,也能夠用服務器的ip做爲域名使用
  • 端口 ,能夠不在瀏覽器中輸入,不輸入的時候瀏覽器默認的端口是80
  • 目錄部分 ,從域名後邊以/開始以/結束,就比如咱們電腦裏邊文件路徑
  • 文件名部分,從域名到路徑,而後同理後邊的是文件命名部分,好比說xxx.html,也能夠不寫這個文件命名,不寫的時候會使用你的服務器設置的默認的文件命名
  • 錨部分 從#開始,#表明頁面中的一個位置,右邊的字符就是這個位置的標識符,若是頁面中有相對應的錨點的或者對應的id的話,瀏覽器會自動根據錨後邊的字符串把可視視圖定位到頁面的錨點位置
    (這個錨部分,用處很是多,到時候單獨整理一盤博客)
  • 參數部分 從? 開始,想必你們以前都見過有些網站的鏈接後邊跟着一些參數,這些參數能夠傳給服務端,並且這一部分容許有多個參數,能夠用&做爲分隔符

跨域的幾種經常使用解決方法

  • script標籤,瀏覽器禁止了跨域的請求訪問,可是能夠引入其餘域的script腳本,並能使用其中的方法,經常使用的瀏覽器能夠經過load事件判斷script是否加載完畢,ie是經過readystatechange屬性

  • postMessage ,這是html5新加的一個新特性,跨文檔消息傳輸Cross Document Messaging。

    • window.postMessage()方法能夠安全的實現跨域通訊,當方法被調用的時候,會在全部頁面的腳本執行完畢以後,向目標窗口發送一個messageEvent的一個消息

    • otherWindow.postMessage(message, targetOrigin, [transfer]);

    • otherWindow
      其餘窗口的一個引用,好比iframe的contentWindow屬性、執行window.open返回的窗口對象、或者是命名過或數值索引的window.frames。

    • message
      將要發送到其餘 window的數據。

    • targetOrigin
      經過窗口的origin屬性來指定哪些窗口能接收到消息事件,其值能夠是字符串"星號"(表示無限制)或者一個URI。在發送消息的時候,若是目標窗口的協議、主機地址或端口這三者的任意一項不匹配targetOrigin提供的值,那麼消息就不會被髮送;只有三者徹底匹配,消息纔會被髮送。

    • transfer 可選
      是一串和message 同時傳遞的 Transferable 對象. 這些對象的全部權將被轉移給消息的接收方,而發送一方將再也不保有全部權。

在接收的window窗口下邊能夠增長一個監聽

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event)
{
  //回調
}

message對象有四個屬性

  • data是第一個傳的參數
  • origin 表示調用 postMessage 時消息發送方窗口的 origin . 包含了協議,域名和端口
  • source屬性 發送消息的窗口對象的引用

  • JsonP跨域

上邊說了script方法 其實這個能夠說成是一種,另外補充下好比img link等 都具備跨域訪問的能力
jsonp其實使用這個特性來實現跨域的,在jsonp裏邊能夠定義回調函數,jsonp並不能替代請求,記得有一次微信公衆號獲取token跨域,jsonp並不能達到相應的效果,感受jsonp 就是把script標籤給封裝了一下

  • CORS訪問驗證

W3C推薦了一種跨域的訪問驗證的機制,即CORS(Cross-Origin Resource Sharing 跨源資源共享)。 這種機制讓Web應用服務器能支持跨站訪問控制,使跨站數據傳輸更加安全,減輕跨域HTTP請求的風險。

CORS驗證機制須要客戶端和服務端協同處理

如今的各主流的瀏覽器都會對動態的跨域請求進行特殊的驗證處理。驗證處理分爲簡單請求驗證處理和預先請求驗證處理。

  • 簡單請求
    當請求的方法是 GET HEAD POST 且請求頭的Content-Type是
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

之一的時候,瀏覽器會直接發送跨域請求,並在請求頭中攜帶訪問地址的header,
當服務端接收到請求以後,會根據本身的跨域規則,經過Access-Control-Allow-Origin和Access-Control-Allow-Methods響應頭,來返回驗證結果。

若是驗證失敗則不會返回資源

  • 預先請求

與簡單請求對應的 ,上述的六個條件,只要有一條不符合,瀏覽器在接收到請求的時候並不會當即執行請求的代碼,而是會先發送一個option請求,用於訪問服務器是否符合規範

正常來說咱們發送請求,好比post請求的時候,瀏覽器也會默認給咱們加上一個options請求,他的主要用途就是獲取服務器支持的http請求房和,和判斷安全,
若是驗證成功則會發送須要執行的請求,若是驗證失敗的時候則會返回一個403的狀態

以上方法基本上就能夠應對大部分的跨域的需求了,還有一些其餘的方法好比說document.domain+iframe

若是是都在一個主源裏邊的話能夠用一下,對於不一樣的源是無能爲力的,沾個例子

//www.a.com上的a.html
document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在這裏操縱b.html
    alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};


//script.a.com上的b.html

document.domain = 'a.com';

好比上邊這個www.a.com和script.a.com 他們的js是能夠互通的,而後說明一下就是咱們在平常用常常看到的www開頭的域名 實際上是二級域名
這裏例子裏邊a.com纔是主域名

以上是我對跨域和經常使用的解決方法的一些認知,有不足之處請多批評,我要去寫bug了

相關文章
相關標籤/搜索