有哪些方式可以實現跨域?

Failed to load http:/ /www.xxx.cn/mock/api/login: Response to preflight request doesn"t pass access control check: No "Access-Control-Allow-Origin" header is present on the requested resource. Origin "http://localhost:8000" is therefore not allowed access. If an opaque response serves your needs, set the request"s mode to "no-cors" to fetch the resource with CORS disabled.

對於這種問題一般可以使用安裝瀏覽器允許跨域的插件、jsonp這類的方式處理,除此外還有其他方法/工具嗎?


1. 本地代理

比如利用 WebpackDevServer 配置本地代理

devServer: {
port: 8080,
proxy: {
"/api": {
target: "http://other-server.example.com"
}
}
}

這樣 `http://localhost:8080/api/getUser.php` 的請求就是後端的介面 `http://other-server.example.com/getUser.php`

2. 瀏覽器配置

以關閉瀏覽器安全策略的方式啟動瀏覽器比如 Chrome:

open -n /Applications/Google Chrome.app/ --args --disable-web-security --user-data-dir

3. JSONP

本質上是利用 script 標籤允許跨域。

如果你需要手寫一個 JSONP 實現:

手寫一個jsonp - CSDN博客

4. CORS

跨域資源共享 CORS 詳解 - 阮一峰的網路日誌

HTTP訪問控制(CORS)

5. document.domain

js設置document.domain實現跨域的注意點分析

6. window.name

利用window.name+iframe跨域獲取數據詳解 - 韓子遲 - 博客園

7. postMessage 實現跨域

[HTML5 postMessage 傳輸與 POST 跨域通訊](HTML5 postMessage 傳輸與 POST 跨域通訊)


一、 跨域資源共享 CORS

最優先的當然是使用 CORS。

CORS 需要瀏覽器和服務端同時支持的,對於兼容性來說主要是ie10+,其它現代瀏覽器都是支持的。

CORS 的請求分兩種,這也是瀏覽器為了安全做的一些處理,不同情況下瀏覽器執行的操作也是不一樣的,主要分為兩種請求,當然這一切我們是不需要做額外處理的,瀏覽器會自動處理的。

非簡單請求一般需要伺服器配置 Access-Control-Request-Method 和 Access-Control-Request-Headers。

二、 jsonp

jsonp = json + padding

其實對於常用性來說,jsonp應該是使用最經常的一種跨域方式了,他不受瀏覽器兼容性的限制。但是他也有他的局限性,只能發送 GET 請求,需要服務端和前端規定好,寫法醜陋。

實質上 jsonp 和 ajax 沒有任何關係,它的原理在於瀏覽器請求 script 資源不受同源策略限制,並且請求到 script 資源後立即執行。

首先全局註冊一個callback回調函數,記住這個函數名字(比如:resolveJson),這個函數接受一個參數,參數是期望的到的服務端返回數據,函數的具體內容是處理這個數據。

然後動態生成一個 script 標籤,src 為:請求資源的地址+獲取函數的欄位名+回調函數名稱,這裡的獲取函數的欄位名是要和服務端約定好的,是為了讓服務端拿到回調函數名稱。(如://www.qiute.com?callbackName=resolveJson)。

在瀏覽器上可以:

function resolveJosn(result) {
console.log(result.name);
}
var jsonpScript= document.createElement("script");
jsonpScript.type = "text/javascript";
jsonpScript.src = "https://www.qiute.com?callbackName=resolveJson";
document.getElementsByTagName("head")[0].appendChild(jsonpScript);

服務端收到這個 script 資源請求,根據後面帶的 query 參數生成 js 片段返回:

resolveJson({name: "qiutc"});

服務端返回這個 script 之後,瀏覽器端獲取到 script 資源,然後會立即執行這個 javascript,也就是上面那個片段。這樣就能根據之前寫好的回調函數處理這些數據了。

三、 document.domain

一個頁面框架(iframe/frame)之間(父子或同輩),是能夠獲取到彼此的window對象的,但是這個 window 不能拿到方法和屬性。

比如:

// 當前頁面域名 https://blog.qiutc.me/a.html

&
function onLoad() {
var iframe =document.getElementById("iframe");
var iframeWindow = iframe.contentWindow; // 這裡可以獲取 iframe 裡面 window 對象,但是幾乎沒用
var doc = iframeWindow.document; // 獲取不到
}
&

&