Web開發中跨域的幾種解決方案
隨著Web App的功能越來越強 各種跨域的需求催生了無數的跨域手法。甚至在HTML5標準中都給出了官方的跨域方法, 也是最近應付面試的需要,拿一篇文章來總結既有的各種跨域手段。
這些跨域通訊的方法大致可以分為兩類:
- 一類是Hack,比如通過
title
,navigation
等物件傳遞資訊,JSONP可以說是一個最優秀的Hack。 - 另一類是HTML5支援,一個是
Access-Control-Allow-Origin
響應頭,一個是window.postMessage
。
設定 document.domain
- 原理:相同主域名不同子域名下的頁面,可以設定
document.domain
讓它們同域 - 限制:同域document提供的是頁面間的互操作,需要載入iframe頁面
下面幾個域名下的頁面都是可以通過document.domain
跨域互操作的: http://a.com/foo
, http://b.a.com/bar
, http://c.a.com/bar
。
但只能以頁面巢狀的方式來進行頁面互操作,比如常見的iframe
方式就可以完成頁面巢狀:
// URL http://a.com/foo
var ifr = document.createElement('iframe');
ifr.src = 'http://b.a.com/bar';
ifr.onload = function(){
var ifrdoc = ifr.contentDocument || ifr.contentWindow .document;
ifrdoc.getElementsById("foo").innerHTML);
};
ifr.style.display = 'none';
document.body.appendChild(ifr);
上述程式碼所在的URL是http://a.com/foo
,它對http://b.a.com/bar
的DOM訪問要求後者將 document.domain
往上設定一級:
// URL http://b.a.com/bar
document.domain = 'a.com'
document.domain
只能從子域設定到主域,往下設定以及往其他域名設定都是不允許的,
在Chrome中給出的錯誤是這樣的:
Uncaught DOMException: Failed to set the 'domain' property on 'Document': 'baidu.com' is not a suffix of 'b.a.com'
有src的標籤
- 原理:所有具有
src
屬性的HTML標籤都是可以跨域的,包括<img>
,<script>
- 限制:需要建立一個DOM物件,只能用於GET方法
在document.body
中append
一個具有src
屬性的HTML標籤, src
屬性值指向的URL會以GET方法被訪問,該訪問是可以跨域的。
其實樣式表的
<link>
標籤也是可以跨域的,只要是有src
或href
的HTML標籤都有跨域的能力。
不同的HTML標籤傳送HTTP請求的時機不同,例如<img>
在更改src
屬性時就會發送請求,而script
, iframe
, link[rel=stylesheet]
只有在新增到DOM樹之後才會傳送HTTP請求:
var img = new Image();
img.src = 'http://some/picture'; // 傳送HTTP請求
var ifr = $('<iframe>', {src: 'http://b.a.com/bar'});
$('body').append(ifr); // 傳送HTTP請求
JSONP
- 原理:
<script>
是可以跨域的,而且在跨域指令碼中可以直接回調當前指令碼的函式。 - 限制:需要建立一個DOM物件並且新增到DOM樹,只能用於GET方法
JSONP利用的是<script>
可以跨域的特性,跨域URL返回的指令碼不僅包含資料,還包含一個回撥:
// URL: http://b.a.com/foo
var data = {
foo: 'bar',
bar: 'foo'
};
callback(data);
該例子只用於示例,實際情況應當考慮名稱隱藏等問題。
然後在我們在主站http://a.com
中,可以這樣來跨域獲取http://b.a.com
的資料:
// URL: http://a.com/foo
var callback = function(data){
// 處理跨域請求得到的資料
};
var script = $('<script>', {src: 'http://b.a.com/bar'});
$('body').append(script);
其實jQuery已經封裝了JSONP的使用,我們可以這樣來:
$.getJSON( "http://b.a.com/bar?callback=callback", function( data ){
// 處理跨域請求得到的資料
});
$.getJSON
與$.get
的區別是前者會把responseText
轉換為JSON,而且當URL具有callback
引數時,
jQuery將會把它解釋為一個JSONP請求,建立一個<script>
標籤來完成該請求。
jQuery.getJSON: If the URL includes the string “callback=?” (or similar, as defined by the server-side API), the request is treated as JSONP instead. See the discussion of the jsonp data type in $.ajax() for more details.)
和所有依賴於建立HTML標籤的方式一樣,JSONP也不支援POST,而GET的資料是放在URL裡的。 雖然[RFC 2616][rfc2610]沒有提到限制到多少, 但提到了伺服器可以對自己認為比較長的URL返回414狀態碼。一般來講URL限長是在2000字元左右。
navigation 物件
- 原理:iframe之間是共享
navigator
物件的,用它來傳遞資訊 - 要求:IE6/7
有些人注意到了IE6/7的一個漏洞:iframe
之間的window.navigator
物件是共享的。
我們可以把它作為一個Messenger,通過它來傳遞資訊。比如一個簡單的委託:
// a.com
navigation.onData(){
// 資料到達的處理函式
}
typeof navigation.getData === 'function'
|| navigation.getData()
// b.com
navigation.getData = function(){
$.get('/path/under/b.com')
.success(function(data){
typeof navigation.onData === 'function'
|| navigation.onData(data)
});
}
與document.navigator
類似,window.name
也是當前視窗所有頁面所共享的。也可以用它來傳遞資訊。
同樣蛋疼的辦法還有傳遞Hash(有些人叫錨點),這是因為每次瀏覽器開啟一個URL時,URL後面的#xxx
部分會保留下來,那麼新的頁面可以從這裡獲得上一個頁面的資料。
跨域資源共享(CORS)
- 原理:伺服器設定
Access-Control-Allow-Origin
HTTP響應頭之後,瀏覽器將會允許跨域請求 - 限制:瀏覽器需要支援HTML5,可以支援POST,PUT等方法
前面提到的跨域手段都是某種意義上的Hack, HTML5標準中提出的跨域資源共享(Cross Origin Resource Share,CORS)才是正道。 它支援其他的HTTP方法如PUT, POST等,可以從本質上解決跨域問題。
例如,從http://a.com
要訪問http://b.com
的資料,通常情況下Chrome會因跨域請求而報錯:
XMLHttpRequest cannot load http://b.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.com' is therefore not allowed access.
錯誤原因是被請求資源沒有設定Access-Control-Allow-Origin
,所以我們在b.com
的伺服器中設定這個響應頭欄位即可:
Access-Control-Allow-Origin: * # 允許所有域名訪問,或者
Access-Control-Allow-Origin: http://a.com # 只允許所有域名訪問
為 xhr
設定 withCredentials
後
CORS 方法跨域還可 攜帶Cookie,但 PUT/POST 請求需要注意處理
preflight 請求。
window.postMessage
- 原理:HTML5允許視窗之間傳送訊息
- 限制:瀏覽器需要支援HTML5,獲取視窗控制代碼後才能相互通訊
這是一個安全的跨域通訊方法,postMessage(message,targetOrigin)
也是HTML5引入的特性。
可以給任何一個window傳送訊息,不論是否同源。第二個引數可以是*
但如果你設定了一個URL但不相符,那麼該事件不會被分發。看一個普通的使用方式吧:
// URL: http://a.com/foo
var win = window.open('http://b.com/bar');
win.postMessage('Hello, bar!', 'http://b.com');
// URL: http://b.com/bar
window.addEventListener('message',function(event) {
console.log(event.data);
});
訪問控制安全的討論
在HTML5之前,JSONP已經成為跨域的事實標準了,jQuery都給出了支援。 值得注意的是它只是Hack,並沒有產生額外的安全問題。 因為JSONP要成功獲取資料,需要跨域資源所在伺服器的配合,比如資源所在伺服器需要自願地回撥一個合適的函式,所以伺服器仍然有能力控制資源的跨域訪問。
跨域的正道還是要使用HTML5提供的CORS頭欄位以及window.postMessage
,
可以支援POST, PUT等HTTP方法,從機制上解決跨域問題。 值得注意的是Access-Control-Allow-Origin
頭欄位是資源所在伺服器設定的,
訪問控制的責任仍然是在提供資源的伺服器一方,這和JSONP是一樣的。
相關推薦
Web開發中跨域的幾種解決方案
隨著Web App的功能越來越強 各種跨域的需求催生了無數的跨域手法。甚至在HTML5標準中都給出了官方的跨域方法, 也是最近應付面試的需要,拿一篇文章來總結既有的各種跨域手段。 這些跨域通訊的方法大致可以分為兩類: 一類是Hack,比如通過title, navigation等物件傳遞資訊,JSONP可
跨域幾種解決方法
跨域 -o head 反向 content nbsp ces methods 函數 1.jsonp 目標服務器設置callback 函數 服務器操作 2.cors 服務器設置header :Access-Control-Allow-Origin 服務器操作
vue開發過程中跨域最簡單解決方案
前言:我們在進行一個專案開發工程中,需要從後端工程師那裡獲取資料庫中的資料。然而前端程式碼和後端程式碼在未打包前是分離的,這就引入了一個“跨域取資料”的問題。 下面,我們就簡單說下,利用vue腳手架生成的專案,在開發過程中怎麼解決此問題。 第一步 找到並開啟config資料夾下的index.js,做如下配置
web開發中常用的幾種統計圖使用
最近,筆者結合自己在公司專案使用統計圖的經驗以及自己的研究,對地圖統計、柱形圖統計、餅圖統計以及折線圖統計這幾種常用的統計作以歸納。主要使用到的js框架是highstock.js,一種完全基於javascript的前端框架。接下來,一一進行講解。 一、地圖
Web學習之跨域問題及解決方案
在做前端開發時,我們時常使用ajax與伺服器通訊獲取資源,享受ajax便利的同時,也知道它有限制:跨域安全限制,即同源策略。 同源策略(SOP),核心是確保不同源提供的檔案之間是相互獨立的 預設情況下,XHR物件只能訪問與包含它的頁面處於同一域中的資源,這種限制可以預防某些惡意攻擊,但同
處理session跨域幾種的方案
常用跨域共用session的是登入模組,我相信很多開發的朋友的都遇到過,只需要一個地方登入,相關聯的網站也是處於登入狀態。兩種情況:一種9streets.cn和a.9streets.cn之間,另一種是a.com b.com之間,這幾天總結了一下處理方法。 方式一:
thinkphp5/tp5介面開發中跨域問題的全部解決方案,options請求的處理
場景還原:由於前後端分離後有可能出現介面的url和我們前端訪問的url不再同一個域名下。這就會導致一個問題,就是瀏覽器的同源策略。對於同源策略如果要正常的使用我們就要處理跨域的問題。當然在跨域中介面傳送前會有一次OPTIONS請求,關於為什麼傳送OPTIONS
使用http-proxy-middleware解決前端開發中跨域的問題
一、使用http-proxy-middleware中介軟體解決跨域問題 本案例中使用基本的webpack及axios請求資料的外掛 1、後端服務是用tornado建立的一個服務(可以根據自
圖片上傳的跨域問題的幾種解決方案和細節及優缺點
方案一 傳到前端伺服器本地,然後用伺服器跨域 ajaxSubmit方式,需要jquery.form.min.js外掛 $("#imgUploadForm").ajaxSubmit({ type: "POST",//提交型別 dataType: "json"
iframe跨域、ajax跨域和JS跨域通訊的幾種解決方案
需要ajax跨域取得資料,如果是在本域中確實沒有問題,但是放到二級域和其他域下瀏覽器直接就彈出提示框:“該頁正在訪問其控制範圍之外的資料,這有些危險,是否繼續" 1.什麼引起了ajax跨域不能的問題 ajax本身實際上是通過XMLHttpRequest物件來進行資
前端跨域幾種方式
div ner dev 修改 ati hash 標簽 nbsp 端口 跨域問題的直接原因是瀏覽器存在同源策略,瀏覽器同源指的是:兩個頁面的協議、端口和主機相同,則兩個頁面具有相同的源。IE下滿足協議、主機相同,就認為是同源。 想象一下,如果沒有同源策略,誰都可以修改你站點
Arcgis Server中跨域問題的解決辦法
arcgis server javascript api開發過程中,在跨域訪問字型、json、地圖服務等資源的時候,會遇到無法訪問的問題,如:“……blocked by CORS”,“……cannot load”,後面常跟一句“No ‘Access-Control-Allow-Origin’
Android第一天---開發中常用的幾種佈局
第一種:LinearLayout:線性佈局 線性佈局是按照處置或者水平進行排布的,預設是水平 屬性:orientation:用來指定當前的線性佈局的排布方向。 wrap_content:包裹內容 match_parent:匹配父類 margin:外邊距 padding
WPF開發中常用的幾種佈局元素
Grid:網格。可以自定義行和列並通過行列的數量、行高和行寬來調整控制元件的佈局,類似於HTML中的Table。 StackPanel:棧式模板。可將包含的元素在豎直或水平方向上排成一條直線,當移除一個元素後,後面的元素會自動向前移動以填充空缺。 Canvas:畫布。內部元素可以使用以畫素為單位的絕對座標
vue-cli 開發中跨域問題和profile模式配置
一、開發環境中跨域 使用 Vue-cli 建立的專案,開發地址是 localhost:8080,需要訪問非本機上的介面http://10.1.0.34:8000/queryRole。不同域名之間的訪問,需要跨域才能正確請求。跨域的方法很多,通常都需要後臺配置,不過 Vue-cli 建立的
SpringBoot:SpringBoot專案中跨域問題的解決
SpringBoot:SpringBoot專案中跨域問題的解決 出於安全原因,瀏覽器禁止對駐留在當前源之外的資源進行AJAX呼叫。 跨源資源共享(CORS)是大多數瀏覽器實現的W3C規範,允許以靈活的方式指定授權的跨域請求型別,而不是使用IFrame或JSON
跨域幾種方式
一、什麼是跨域 JavaScript出於安全方面的考慮,不允許跨域呼叫其他頁面的物件。那什麼是跨域呢,簡單地理解就是因為JavaScript同源策略的限制, a.com 域名下的js無法操作 b.com 或是 c.a.com 域名下的物件。 有一點必須要注意:
web 專案解決跨域問題終極解決方案
一.跨域問題的由來 二.怎麼就算跨域(同源的定義) 三.常見跨域解決方法 四.總結 一.跨域問題的由來 為什麼會產生這樣一個問題,擺在我們面前呢?? 理解跨域,首先必須要了解同源策略。同源策略是瀏覽器上為安全性考慮實施的非常重要的安全策略。 為了防止某些文件或指令碼載入別
分類任務中資料類別不平衡問題的幾種解決方案
類別不平衡(class-imbalance),是指分類任務中不同類別的訓練樣例數目差別很大的情況(例如,訓練集正類樣例10個,反類樣例90個),本文假設正類樣例較少,反類樣例較多。 現有解決方案大體分為三類,如下文所示。 欠取樣(undersampling) 欠取樣方法,即去除一
SpringBoot中跨域問題的解決
什麼叫跨域 瀏覽器對於javascript的同源策略的限制,例如a.cn下面的js不能呼叫b.cn中的js,物件或資料(因為a.cn和b.cn是不同域),所以跨域就出現了.簡而言之,就是本地伺服器不能呼叫其他伺服器的資源。 導致的問題: web端收不到伺服器端的返回訊