這個策略對於JavaScript程式碼能夠存取的頁面內容做了很重要的限制,即JavaScript只能存取與包含它的文件在同一網域下的內容。
JavaScript這個安全策略在進行多iframe或多視窗程式設計、以及Ajax程式設計時顯得格外重要。根據這個策略,在baidu.com下的頁面中包含的JavaScript程式碼,不能存取在google.com網域下的頁面內容;甚至不同的子網域之間的頁面也不能透過JavaScript程式碼互相存取。對於Ajax的影響在於,透過XMLHttpRequest實現的Ajax請求,不能向不同的網域提交請求,例如,在abc.example.com下的頁面,不能向def.example.com提交Ajax請求,等等。
然而,當進行一些比較深入的前端編程的時候,不可避免地需要進行跨域操作,這時候「同源策略」就顯得過於苛刻。本文就這個問題,概括了跨域所需的一些技術。
下面我們分兩種情況討論跨域技術:首先討論不同子域的跨域技術,然後討論完全不同域的跨域技術。
(一)不同子域的跨域技術。
我們分成兩個問題分別討論:第一個問題是如何跨不同子域進行JavaScript呼叫;第二個問題是如何向不同子域提交Ajax請求。
先來解決第一個問題,假設example.com網域下有兩個不同子網域:abc.example.com和def.example.com。現在假設在def.example.com下面有一個頁面,裡面定義了一個JavaScript函數:
.....
}
我們想要在abc.example.com下的某個頁面中呼叫上面的函數。再假設我們要討論的abc.example.com下面的這個頁面是以iframe形式嵌入在def.example.com下面那個頁面裡的,這樣我們可能試圖在iframe裡做如下調用:
好,我們注意到,這個呼叫是被前面講到的「同源策略」所禁止的,JavaScript引擎會直接拋出一個異常。
為了實現上述調用,我們可以透過修改兩個頁面的domain屬性的方法來做到。例如,我們可以將上面在abc.example.com和def.example.com下的兩個頁面的頂端都加上如下的JavaScript程式碼片段:
這樣,兩個頁面就變成同域了,前面的呼叫也可以正常執行了。
這裡要注意的一點是,一個頁面的document.domain屬性只能設定成一個更頂級的網域(除了一級網域),但不能設定成比目前網域更深層的子網域。例如,abc.example.com的頁面只能將它的domain設定成example.com,不能設定成sub.abc.example.com,當然也不能設定成一級網域com。
上面的例子討論的是兩個頁面屬於iframe嵌套關係的情況,當兩個頁面是打開與被打開的關係時,原理也完全一樣。
下面我們來解決第二個問題:如何向不同子網域提交Ajax請求。
通常情況下,我們會用與下面類似的程式碼來建立一個XMLHttpRequest物件:
return new XMLHttpRequest();
},
function() {
>},
function() {
return new ActiveXObject("Microsoft.XMLHTTP");
}];
function newRequest() {
for (var i = 0 i & lt; factories.length; i ) {
try {
} catch(e) {}
}
return null;
}
上面的程式碼中引用ActiveXObject,是為了相容於IE6系列瀏覽器。每次我們呼叫newRequest函數,就獲得了一個剛剛建立的Ajax對象,然後用這個Ajax物件來發送HTTP請求。例如,下面的程式碼向abc.example.com發送了一個GET請求:
var request = newRequest();
request.open("GET", "http://abc.example.com" );
request.send(null);
假設上面的程式碼包含在一個abc.example.com網域下的頁面裡,則這個GET請求可以正常發送成功,沒有任何問題。然而,如果現在要向def.example.com發送請求,則出現跨域問題,JavaScript引擎拋出例外。
解決的方法是,在def.example.com域下放置一個跨域文件,假設叫crossdomain.html;然後將前面的newRequest函數的定義移到這個跨域文件中;最後像之前修改document. domain值的做法一樣,在crossdomain.html檔案和abc.example.com域下呼叫Ajax的頁面頂端,都加上:
程式碼如下:
document.domain = "example.com";複製代碼
複製程式碼
程式碼如下:
var request = window.frames["xd_Rerame"].new ();這樣取得的request對象,就可以向http://def.example.com發送HTTP請求了。
(二)完全不同域的跨域技術。
如果頂級網域都不相同,例如example1.com和example2.com之間想透過JavaScript在前端通信,則所需要的技術更複雜些。
在講解不同域的跨域技術之前,我們先明確一點,下面要講的技術也同樣適用於前面跨不同子域的情況,因為跨不同子域只是跨域問題的一個特例。當然,在適當的情況下使用適當的技術,能夠確保更優的效率和更高的穩定性。
簡言之,根據不同的跨域需求,跨域技術可以歸為下面幾類:
1、JSONP跨域GET請求
2、透過iframe實現跨域 3、flash跨域HTTP請求
4、window.postMessage以下詳細介紹各種技術。
1. JSONP。
程式碼如下:
当GET请求从http://example2.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://example1.com/index.php页面中的一个callback函数。
JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
2. 通过iframe实现跨域。
iframe跨域的方式,功能强于JSONP,它不仅能用来跨域完成HTTP请求,还能在前端跨域实现JavaScript调用。因此,完全不同域的跨域问题,通常采用iframe的方式来解决。
与JSONP技术通过创建<script>节点向不同的域提交GET请求的工作方式类似,我们也可以通过在http://example1.com/index.php页面中创建指向http://example2.com/getinfo.php的iframe节点跨域提交GET请求。然而,请求返回的结果无法回调http://example1.com/index.php页面中的callback函数,因为受到“同源策略”的影响。<br><br>为了解决这个问题,我们需要在example1.com下放置一个跨域文件,比如路径是http://example1.com/crossdomain.html。<br><br>当http://example2.com/getinfo.php这个请求返回结果的时候,它大体上有两个选择。<BR>第一个选择是,它可以在iframe中做一个302跳转,跳转到跨域文件http://example1.com/crossdomain.html,同时将返回结果经过URL编码之后作为参数缀在跨域文件URL后面,例如http://example1.com/crossdomain.html?result=<URL-Encoding-Content>。<br><br>另一个选择是,它可以在返回的页面中再嵌入一个iframe,指向跨域文件,同时也是将返回结果经过URL编码之后作为参数缀在跨域文件URL后面。<br><br>在跨域文件中,包含一段JavaScript代码,这段代码完成的功能,是从URL中提取结果参数,经过一定处理后调用原来的http://example1.com/index.php页面中的一个预先约定好的callback函数,同时将结果参数传给这个函数。http://example1.com/index.php页面和跨域文件是在同一个域下的,因此这个函数调用可以通过。跨域文件所在iframe和原来的http://example1.com/index.php页面的关系,在前述第一种选择下,后者是前者的父窗口,在第二种选择下,后者是前者的父窗口的父窗口。<br><br>根据前面的叙述,有了跨域文件之后,我们就可以实现通过iframe方式在不同域之间进行JavaScript调用。这个调用过程可以完全跟HTTP请求无关,例如有些站点可以支持动态地调整在页面中嵌入的第三方iframe的高度,这其实是通过在第三方iframe里面检测自己页面的高度变化,然后通过跨域方式的函数调用将这个变化告知父窗口来完成的。<br><br>既然利用iframe可以实现跨域JavaScript调用,那么跨域提交POST请求等其它类型的HTTP请求就不是难事。例如我们可以跨域调用目标域的JavaScript代码在目标域下提交Ajax请求(GET/POST/etc.),然后将返回的结果再跨域传原来的域。<br><br>使用iframe跨域,优点是功能强大,支持各种浏览器,几乎可以完成任何跨域想做的事情;缺点是实现复杂,要处理很多浏览器兼容问题,并且传输的数据不宜过大,过大了可能会超过浏览器对URL长度的限制,要考虑对数据进行分段传输等。</script>
3. 利用flash实现跨域HTTP请求
据称,flash在浏览器中的普及率高达90%以上。
flash代码和JavaScript代码之间可以互相调用,并且flash的“安全沙箱”机制与JavaScript的安全机制并不尽相同,因此,我们可以利用flash来实现跨域提交HTTP请求(支持GET/POST等)。
例如,我们用浏览器访问http://example1.com/index.php这个页面,在这个页面中引用了http://example2.com/flash.swf这个flash文件,然后在flash代码中向http://example3.com/webservice.php发送HTTP请求。
这个请求能否被成功发送,取决于在example3.com的根路径下是否放置了一个crossdomain.xml以及这个crossdomain.xml的配置如何。flash的“安全沙箱”会保证:仅当example3.com服务器在根路径下确实放置了crossdomain.xml文件并且在这个文件中配置了允许接受来自example2.com的flash的请求时,这个请求才能真正成功。下面是一个crossdomain.xml文件内容的例子:
4. window.postMessage
window.postMessage是HTML標準的下一個版本HTML5支援的新功能。受目前網路技術突飛猛進的影響,瀏覽器跨域通訊的需求越來越強烈,HTML標準終於把跨域通訊考慮進去了。但目前HTML5仍然只是一個draft。 window.postMessage是一個安全的實作直接跨域通訊的方法。但目前並不是所有瀏覽器都能支持,只有Firefox 3、Safari 4和IE8可以支援這個呼叫。
使用它向其它視窗發送訊息的呼叫方式大概如下:
otherWindow.postMessage(message, targetOrigin);
程式碼如下:
window.addEventListener("message", receiveMessage, false);}
訊息包含三個屬性:data、origin(攜帶發送視窗所在網域的真實資訊)和source (代表發送視窗的handle)。
安全性考量:使用window.postMessage,必需要使用訊息的origin和source屬性來驗證傳送者的身份,否則會造成XSS漏洞。
window.postMessage在功能上同iframe實現的跨域功能同樣強大,並且使用簡單,效率更高,但缺點是它目前在瀏覽器兼容方面有待提高。
需要對原文補充的是,在IE6,IE7下可利用IE的Opener可賦值為Object或Function的漏洞,提供postMessage方案的補充方案:主頁:
程式碼如下:
< ;/head>
用iframe內嵌其他網域下的頁面:
程式碼如下:
onload = function(){
地alert(arg);
alert('由函數執行在iframe 中');
}
window.opener.funcInParent('來自iframe 的數據')
}
}
>
註:postMessage 方式正考慮以方便的速度得到各種新瀏覽器的支持,應可接受的商品。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3漢化版
中文版,非常好用

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

記事本++7.3.1
好用且免費的程式碼編輯器

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 Linux新版
SublimeText3 Linux最新版