前端面試查漏補缺--(三) 跨域及常看法決辦法

前言

本系列最開始是爲了本身面試準備的.後來發現整理愈來愈多,差很少有十二萬字符,最後決定仍是分享出來給你們.javascript

爲了分享整理出來,花費了本身大量的時間,起碼是隻本身用的三倍時間.若是喜歡的話,歡迎收藏,關注我!謝謝!html

文章連接

合集篇:

前端面試查漏補缺--Index篇(12萬字符合集) 包含目前已寫好的系列其餘十幾篇文章.後續新增值文章不會再在每篇添加連接,強烈建議議點贊,關注合集篇!!!!,謝謝!~前端

後續更新計劃

後續還會繼續添加設計模式,前端工程化,項目流程,部署,閉環,vue常考知識點 等內容.若是以爲內容不錯的話歡迎收藏,關注我!謝謝!vue

求一分內推

目前本人也在準備跳槽,但願各位大佬和HR小姐姐能夠內推一份靠譜的武漢 前端崗位!郵箱:bupabuku@foxmail.com.謝謝啦!~java

概述

由於瀏覽器出於安全考慮,有了同源策略,這樣就致使只要協議、域名、端口有任何一個不一樣,都被看成是不一樣的域。也就是說,若是協議、域名或者端口有一個不一樣就是跨域,Ajax 請求就會失敗。node

常見跨域的解決辦法

JSONP

JSONP 的原理很簡單,就是利用 <script> 標籤沒有跨域限制的漏洞。經過 <script> 標籤指向一個須要訪問的地址並提供一個回調函數來接收數據當須要通信時。webpack

<script src="http://domain/api?param1=a&param2=b&callback=jsonp"></script>
<script>
    function jsonp(data) {
    	console.log(data)
	}
</script>

複製代碼

JSONP 使用簡單且兼容性不錯,可是只限於 get 請求。nginx

在開發中可能會遇到多個 JSONP 請求的回調函數名是相同的,這時候就須要本身封裝一個 JSONP,如下是簡單實現web

function jsonp(url, jsonpCallback, success) {
  let script = document.createElement('script')
  script.src = url
  script.async = true
  script.type = 'text/javascript'
  window[jsonpCallback] = function(data) {
    success && success(data)
  }
  document.body.appendChild(script)
}
jsonp('http://xxx', 'callback', function(value) {
  console.log(value)
})
複製代碼

CORS

CORS(Cross-Origin ResourceSharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與服務器應該如何溝通。面試

CORS背後的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功仍是失敗。 目前,全部瀏覽器都支持該功能,IE瀏覽器不能低於IE10。 由於須要經過 XDomainRequest 來實現。

整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於開發者來講,CORS通訊與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。

所以,實現CORS通訊的關鍵是服務器。只要服務器實現了CORS接口,就能夠跨源通訊。

服務器端對於CORS的支持,主要就是經過設置Access-Control-Allow-Origin來進行的。該屬性表示哪些域名能夠訪問資源,若是設置通配符則表示全部網站均可以訪問資源。若是瀏覽器檢測到相應的設置,就能夠容許Ajax進行跨域的訪問。

postMessage

這是由H5提出來的的API,IE8以上支持這個功能。window.postMessage() 方法能夠安全地實現跨源通訊。一般,對於兩個不一樣頁面的腳本,只有當執行它們的頁面位於具備相同的協議(一般爲https),端口號(443爲https的默認值),以及主機 (兩個頁面的模數 Document.domain設置爲相同的值) 時,這兩個腳本才能相互通訊。window.postMessage() 方法提供了一種受控機制來規避此限制,只要正確的使用,這種方法就很安全。

window.postMessage() 方法被調用時,會在全部頁面腳本執行完畢以後,向目標窗口派發一個 MessageEvent 消息。

該MessageEvent消息有四個屬性須要注意:

  • message 屬性表示該message 的類型;
  • data 屬性爲 window.postMessage 的第一個參數;
  • origin 屬性表示調用window.postMessage() 方法時調用頁面的當前狀態;
  • source 屬性記錄調用 window.postMessage() 方法的窗口信息。

語法

otherWindow.postMessage(message, targetOrigin);

  • otherWindow:指目標窗口,也就是給哪一個window發消息,是 window.frames 屬性的成員或者由 window.open 方法建立的窗口
  • message: 是要發送的消息,類型爲 String、Object (IE八、9 不支持)
  • targetOrigin: 是限定消息接收範圍,不限制請使用 '*

例子:

A頁面經過postMessage方法發送消息:

window.onload = function() {  
    var ifr = document.getElementById('ifr');  
    var targetOrigin = "http://www.google.com";  
    ifr.contentWindow.postMessage('hello world!', targetOrigin);  
};
複製代碼

B頁面經過message事件監聽並接受消息:

var onmessage = function (event) {  
  var data = event.data;//消息 
  var origin = event.origin;//消息來源地址 
  var source = event.source;//源Window對象 
  if(origin=="http://www.baidu.com"){  
console.log(data);//hello world! 
  }  
};  
if (typeof window.addEventListener != 'undefined') {  
  window.addEventListener('message', onmessage, false);  
} else if (typeof window.attachEvent != 'undefined') {  
  //for ie 
  window.attachEvent('onmessage', onmessage);  
}
複製代碼

nginx代理跨域

跨域原理: 同源策略是瀏覽器的安全策略,不是HTTP協議的一部分。服務器端調用HTTP接口只是使用HTTP協議,不會執行JS腳本,不須要同源策略,也就不存在跨越問題。

實現思路: 經過nginx配置一個代理服務器(域名與domain1相同,端口不一樣)作跳板機,反向代理訪問domain2接口,而且能夠順便修改cookie中domain信息,方便當前域cookie寫入,實現跨域登陸。

nginx具體配置:

#proxy服務器
server {
    listen       81;
    server_name  www.domain1.com;

    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie裏域名
        index  index.html index.htm;

        # 當用webpack-dev-server等中間件代理接口訪問nignx時,此時無瀏覽器參與,故沒有同源限制,下面的跨域配置可不啓用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #當前端只跨域不帶cookie時,可爲*
        add_header Access-Control-Allow-Credentials true;
    }
}
複製代碼

WebSocket與NodeJs中間件跨域等其餘方法

這些方法除了nodejs用得都不是特別多,WebSocket不會專門用來作跨域,而是做爲消息推送或者聊天等.

其他的方法,詳細能夠參考: 前端常見跨域解決方案(全)

相關文章
相關標籤/搜索