有哪些方式可以實現跨域?
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
&
&
data.html 頁面里的代碼很簡單,就是給當前的 window.name 設置一個 a.html 頁面想要得到的數據值。data.htm l里的代碼:
&
之後 a.html 頁面中使用一個隱藏的 iframe 來充當一個中間人角色,由 iframe 去獲取 data.html 的數據,然後 a.html 再去得到 iframe 獲取到的數據。
比如:
// a.html
&
&
&
&
&
&
&
&
&
五、 window.postMessage
window.postMessage(message, targetOrigin) 方法是 html5 標準新引進的特性,可以使用它來向其它的 window 對象發送消息,無論這個 window 對象是屬於同源或不同源。兼容性:
調用postMessage方法的window對象是指要接收消息的那一個window對象,該方法的第一個參數message為要發送的消息,類型只能為字元串;第二個參數targetOrigin用來限定接收消息的那個window對象所在的域,如果不想限定域,可以使用通配符 * 。
舉例,在主頁面:
&
&
在 iframe 頁面:
&
六、 CSST (CSS Text Transformation)
CSST 一種用 CSS 跨域傳輸文本的方案,讀取 CSS3 content 屬性獲取傳送內容。
通過創建一個 link 請求到 css 文件,然後通過 `computedStyle = window.getComputedStyle` 獲取到指定元素的 style 對象,再通過 `computedStyle .content` 獲取到內容。
在頁面中:
function handle (fn) {
var computedStyle = getComputedStyle(span, false);
var content = computedStyle.content;
console.log("content: %s", content);
var match = content.match(/[w+=/]+/);
// base64 解碼
if (match) {
try {
content = decodeURIComponent(escape(atob(match[0])));
} catch (ex) {
fn(ex);
return;
}
}
fn(content);
}
服務端收到這個 css 請求後返回一段 css 片段:
@keyframes csst {
from {}
to {
color: red;
}
}
@-webkit-keyframes csst {
from {}
to {
color: red;
}
}
#csst {
content: "${text}";
animation: cost 2s;
-webkit-animation: ${id} 2s;
}
這裡的 `text` 就是我們可以獲取到的數據;
之後可以通過監聽函數 animationstart/webkitAnimationStart 來判斷接收到 css 文件的時機:
// 我們在服務端給 #csst 元素設置了動畫(當然這個是可配置的)
var cs = document.getElementById("cast");
cs.addEventListener("animationstart", handler, false);
cs.addEventListener("webkitAnimationStart", handler, false);
可以看出該方法和 jsonp 的方案的非常類似的。
七、 利用flash
不多講這個了,註定消亡...
以上內容來自我的知乎專欄:關於前端跨域的整理
還可以關注我的博客:阿城的日誌
1.自己用node寫一層中間代理,所有請求用node攔截轉發。
2.用Nginx進行代理。3.用前端腳手架工具。本質上就是再架一層服務,通過這個服務去請求別的服務,就沒有跨域問題了。寫了一些簡單的小demo,可以快速入門跨域。跨域demo包括CORS、JSONP、Proxy後端代理、html5新特性postMessage、window.name、location.hash、document.domain、websocket。
github地址:200+star
FatDong1/cross-domaingithub.comiframe配合document.domain,jsonp,反向代理等等
ProxypostMessagewebsocketjsonp
跨域訪問涉及兩個方面,一個是瀏覽器,一個是伺服器。
也就是說要實現跨域訪問,單方面進行是不夠的。
不過,現代瀏覽器已經自帶跨域處理。
在一般場景中,只需要在伺服器設置跨域即可
CORS跨域。
或者使用後端代理,比如訪問你的localhost:8000/mock/api/login的時候就,後台接收到這個/mock/api/login,替你發送到http:/ /www.xxx.cn/mock/api/login,再把得到的東西給你返回來,也成,我記得webpack或者nginx都可以實現類似的功能。
還有比較low的jsonp,不太推薦,只能get
還有反向代理;
h5的Access-Control-Allow-Origin:*;
推薦閱讀:
※为什么form表单提交没有跨域问题,但ajax提交有跨域问题?
※用於驗證的 Passport.js 與 JsonWebToken 是什麼關係?
※「遵循XXX開源協議」這句話規定了什麼,我要把某個js工具用在項目中,我具體要做哪些事情才算遵循協議?
※什麼是JS跨域訪問?
※請問如果一個線程能夠非同步執行,是否是因為另一個線程幫其承擔了同步的操作?
TAG:前端開發 | JavaScript | 前端工程化 | webpack |