亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript同源策略和跨域訪問實(shí)例詳解

 更新時間:2018年04月03日 14:12:12   作者:襲烽  
這篇文章主要介紹了JavaScript同源策略和跨域訪問,結(jié)合實(shí)例形式較為詳細(xì)的分析了javascript同源策略與跨域訪問的原理、實(shí)現(xiàn)、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了JavaScript同源策略和跨域訪問。分享給大家供大家參考,具體如下:

1. 什么是同源策略

理解跨域首先必須要了解同源策略。同源策略是瀏覽器上為安全性考慮實(shí)施的非常重要的安全策略。

何謂同源:

URL由協(xié)議、域名、端口和路徑組成,如果兩個URL的協(xié)議、域名和端口相同,則表示他們同源。

同源策略:

瀏覽器的同源策略,限制了來自不同源的"document"或腳本,對當(dāng)前"document"讀取或設(shè)置某些屬性。 (白帽子講web安全[1])

從一個域上加載的腳本不允許訪問另外一個域的文檔屬性。

舉個例子:

比如一個惡意網(wǎng)站的頁面通過iframe嵌入了銀行的登錄頁面(二者不同源),如果沒有同源限制,惡意網(wǎng)頁上的javascript腳本就可以在用戶登錄銀行的時候獲取用戶名和密碼。

在瀏覽器中,<script>、<img>、<iframe>、<link>等標(biāo)簽都可以加載跨域資源,而不受同源限制,但瀏覽器限制了JavaScript的權(quán)限使其不能讀、寫加載的內(nèi)容。

另外同源策略只對網(wǎng)頁的HTML文檔做了限制,對加載的其他靜態(tài)資源如javascript、css、圖片等仍然認(rèn)為屬于同源。

代碼示例(http://localhost:8080/和http://localhost:8081由于端口不同而不同源):

http://localhost:8080/test.html

<html>
  <head><title>test same origin policy</title></head>
  <body>
    <iframe id="test" src="http://localhost:8081/test2.html"></iframe>
    <script type="text/javascript">
      document.getElementById("test").contentDocument.body.innerHTML = "write somthing";
    </script>
  </body>
</html>

http://localhost:8081/test2.html

<html>
  <head><title>test same origin policy</title></head>
  <body>
    Testing.
  </body>
</html>

在Firefox中會得到如下錯誤:

Error: Permission denied to access property 'body'

Document對象的domain屬性存放著裝載文檔的服務(wù)器的主機(jī)名,可以設(shè)置它。

例如來自"blog.jb51.net"和來自"bbs.jb51.net"的頁面,都將document.domain設(shè)置為"jb51.net",則來自兩個子域名的腳本即可相互訪問。

出于安全的考慮,不能設(shè)置為其他主domain,比如http://chabaoo.cn/不能設(shè)置為sina.com

2. Ajax跨域

Ajax (XMLHttpRequest)請求受到同源策略的限制。

Ajax通過XMLHttpRequest能夠與遠(yuǎn)程的服務(wù)器進(jìn)行信息交互,另外XMLHttpRequest是一個純粹的Javascript對象,這樣的交互過程,是在后臺進(jìn)行的,用戶不易察覺。

因此,XMLHTTP實(shí)際上已經(jīng)突破了原有的Javascript的安全限制。

舉個例子:

假設(shè)某網(wǎng)站引用了其它站點(diǎn)的javascript,這個站點(diǎn)被compromise并在javascript中加入獲取用戶輸入并通過ajax提交給其他站點(diǎn),這樣就可以源源不斷收集信息。

或者某網(wǎng)站因?yàn)榇嬖诼┒磳?dǎo)致XSS注入了javascript腳本,這個腳本就可以通過ajax獲取用戶信息并通過ajax提交給其他站點(diǎn),這樣就可以源源不斷收集信息。

如果我們又想利用XMLHTTP的無刷新異步交互能力,又不愿意公然突破Javascript的安全策略,可以選擇的方案就是給XMLHTTP加上嚴(yán)格的同源限制。

這樣的安全策略,很類似于Applet的安全策略。IFrame的限制還僅僅是不能訪問跨域HTMLDOM中的數(shù)據(jù),而XMLHTTP則根本上限制了跨域請求的提交。(實(shí)際上下面提到了CORS已經(jīng)放寬了限制)

隨著Ajax技術(shù)和網(wǎng)絡(luò)服務(wù)的發(fā)展,對跨域的要求也越來越強(qiáng)烈。下面介紹Ajax的跨域技術(shù)。

2.1 JSONP

JSONP技術(shù)實(shí)際和Ajax沒有關(guān)系。我們知道<script>標(biāo)簽可以加載跨域的javascript腳本,并且被加載的腳本和當(dāng)前文檔屬于同一個域。因此在文檔中可以調(diào)用/訪問腳本中的數(shù)據(jù)和函數(shù)。如果javascript腳本中的數(shù)據(jù)是動態(tài)生成的,那么只要在文檔中動態(tài)創(chuàng)建<script>標(biāo)簽就可以實(shí)現(xiàn)和服務(wù)端的數(shù)據(jù)交互。

JSONP就是利用<script>標(biāo)簽的跨域能力實(shí)現(xiàn)跨域數(shù)據(jù)的訪問,請求動態(tài)生成的JavaScript腳本同時帶一個callback函數(shù)名作為參數(shù)。其中callback函數(shù)本地文檔的JavaScript函數(shù),服務(wù)器端動態(tài)生成的腳本會產(chǎn)生數(shù)據(jù),并在代碼中以產(chǎn)生的數(shù)據(jù)為參數(shù)調(diào)用callback函數(shù)。當(dāng)這段腳本加載到本地文檔時,callback函數(shù)就被調(diào)用。

第一個站點(diǎn)的測試頁面(http://localhost:8080/test.html):

<script src="http://localhost:8081/test_data.js">
  <script>
    function test_handler(data) {
      console.log(data);
    }
</script>

服務(wù)器端的Javascript腳本(http://localhost:8081/test_data.js):

test_handler('{"data": "something"}');

為了動態(tài)實(shí)現(xiàn)JSONP請求,可以使用Javascript動態(tài)插入<script>標(biāo)簽:

<script type="text/javascript">
    // this shows dynamic script insertion
    var script = document.createElement('script');
    script.setAttribute('src', url);
    // load the script
    document.getElementsByTagName('head')[0].appendChild(script);
</script>

JSONP協(xié)議封裝了上述步驟,jQuery中統(tǒng)一是現(xiàn)在AJAX中(其中data type為JSONP):

http://localhost:8080/test?callback=test_handler

為了支持JSONP協(xié)議,服務(wù)器端必須提供特別的支持[2],另外JSONP只支持GET請求。

2.2 Proxy

使用代理方式跨域更加直接,因?yàn)镾OP的限制是瀏覽器實(shí)現(xiàn)的。如果請求不是從瀏覽器發(fā)起的,就不存在跨域問題了。

使用本方法跨域步驟如下:

1. 把訪問其它域的請求替換為本域的請求

2. 本域的請求是服務(wù)器端的動態(tài)腳本負(fù)責(zé)轉(zhuǎn)發(fā)實(shí)際的請求

各種服務(wù)器的Reverse Proxy功能都可以非常方便的實(shí)現(xiàn)請求的轉(zhuǎn)發(fā),如Apache httpd + mod_proxy。

Eg.

為了通過Ajax從http://localhost:8080訪問http://localhost:8081/api,可以將請求發(fā)往http://localhost:8080/api。

然后利用Apache Web服務(wù)器的Reverse Proxy功能做如下配置:

ProxyPass /api http://localhost:8081/api

2.3 CORS

2.3.1 Cross origin resource sharing

“Cross-origin resource sharing (CORS) is a mechanism that allows a web page to make XMLHttpRequests to another domain. Such "cross-domain" requests would otherwise be forbidden by web browsers, per the same origin security policy. CORS defines a way in which the browser and the server can interact to determine whether or not to allow the cross-origin request. It is more powerful than only allowing same-origin requests, but it is more secure than simply allowing all such cross-origin requests.” ----Wikipedia[3]

通過在HTTP Header中加入擴(kuò)展字段,服務(wù)器在相應(yīng)網(wǎng)頁頭部加入字段表示允許訪問的domain和HTTP method,客戶端檢查自己的域是否在允許列表中,決定是否處理響應(yīng)。

實(shí)現(xiàn)的基礎(chǔ)是JavaScript不能夠操作HTTP Header。某些瀏覽器插件實(shí)際上是具有這個能力的。

服務(wù)器端在HTTP的響應(yīng)頭中加入(頁面層次的控制模式):

Access-Control-Allow-Origin: example.com
Access-Control-Request-Method: GET, POST
Access-Control-Allow-Headers: Content-Type, Authorization, Accept, Range, Origin
Access-Control-Expose-Headers: Content-Range
Access-Control-Max-Age: 3600

多個域名之間用逗號分隔,表示對所示域名提供跨域訪問權(quán)限。"*"表示允許所有域名的跨域訪問。

客戶端可以有兩種行為:

1. 發(fā)送OPTIONS請求,請求Access-Control信息。如果自己的域名在允許的訪問列表中,則發(fā)送真正的請求,否則放棄請求發(fā)送。

2. 直接發(fā)送請求,然后檢查response的Access-Control信息,如果自己的域名在允許的訪問列表中,則讀取response body,否則放棄。

本質(zhì)上服務(wù)端的response內(nèi)容已經(jīng)到達(dá)本地,JavaScript決定是否要去讀取。

Support: [Javascript Web Applications]
* IE >= 8 (需要安裝caveat)
* Firefox >= 3
* Safari 完全支持
* Chrome 完全支持
* Opera 不支持

 2.3.2 測試

測試頁面http://localhost:8080/test3.html使用jquery發(fā)送Ajax請求。

<html>
    <head><title>testing cross sop</title></head>
    <body>
      Testing.
      <script src="jquery-2.0.0.min.js"></script>
      <script type='text/javascript'>
        $.ajax({
          url: 'http://localhost:8000/hello',
          success: function(data) {
            alert(data);
          },
          error: function() {
            alert('error');
          }
        });
      </script>
    </body>
</html>

測試Restful API(http://localhost:8000/hello/{name})使用bottle.py來host。

from bottle import route, run, response
@route('/hello')
def index():
  return 'Hello World.'
run(host='localhost', port=8000)

測試1:

測試正常的跨域請求的行為。

測試結(jié)果:

1. 跨域GET請求已經(jīng)發(fā)出,請求header中帶有

    Origin    http://localhost:8080

2. 服務(wù)器端正確給出response

3. Javascript拒絕讀取數(shù)據(jù),在firebug中發(fā)現(xiàn)reponse為空,并且觸發(fā)error回調(diào)

測試2:

測試支持CORS的服務(wù)器的跨域請求行為。

對Restful API做如下改動,在response中加入header:

def index():
  #Add CORS header#
  response.set_header("Access-Control-Allow-Origin", "http://localhost:8080")
  return 'Hello World.'

測試結(jié)果:

1. 跨域GET請求已經(jīng)發(fā)出,請求header中帶有

Origin    http://localhost:8080

2. 服務(wù)器端正確給出response

3. 客戶端正常獲取數(shù)據(jù)

測試3:

測試OPTIONS請求獲取CORS信息。
對客戶端的Ajax請求增加header:

$.ajax({
 url: 'http://localhost:8000/hello',
 headers: {'Content-Type': 'text/html'},
 success: function(data) {
   alert(data);
 },
 error: function() {
   alert('error');
 }
});

對Restful API做如下改動:

@route('/hello', method = ['OPTIONS', 'GET'])
def index():
  if request.method == 'OPTIONS':
    return ''
  return 'Hello World.'

測試結(jié)果:

1. Ajax函數(shù)會首先發(fā)送OPTIONS請求
2. 針對OPTIONS請求服務(wù)器
3. 客戶端發(fā)現(xiàn)沒有CORS header后不會發(fā)送GET請求

測試4:

增加服務(wù)器端對OPTIONS方法的處理。

對Restful API做如下改動:

@route('/hello', method = ['OPTIONS', 'GET'])
def index():
    response.headers['Access-Control-Allow-Origin'] = 'http://localhost:8080'
    response.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS'
    response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type'
    if request.method == 'OPTIONS':
      return ''
    return 'Hello World.'

測試結(jié)果:

1. Ajax函數(shù)會首先發(fā)送OPTIONS請求
2. 針對OPTIONS請求服務(wù)器
3. 客戶端匹配CORS header中的allow headers and orgin后會正確發(fā)送GET請求并獲取結(jié)果

測試發(fā)現(xiàn),Access-Control-Allow-Headers是必須的。

CORS協(xié)議提升了Ajax的跨域能力,但也增加了風(fēng)險。一旦網(wǎng)站被注入腳本或XSS攻擊,將非常方便的獲取用戶信息并悄悄傳遞出去。

4. Cookie 同源策略

Cookie中的同源只關(guān)注域名,忽略協(xié)議和端口。所以https://localhost:8080/和http://localhost:8081/的Cookie是共享的。

5. Flash/SilverLight跨域

瀏覽器的各種插件也存在跨域需求。通常是通過在服務(wù)器配置crossdomain.xml[4],設(shè)置本服務(wù)允許哪些域名的跨域訪問。

客戶端會首先請求此文件,如果發(fā)現(xiàn)自己的域名在訪問列表里,就發(fā)起真正的請求,否則不發(fā)送請求。

<?xml version="1.0"?>
  <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
  <cross-domain-policy>
  <allow-access-from domain="*"/>
  <allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

通常crossdomain.xml放置在網(wǎng)站根目錄。

6. 總結(jié)

互聯(lián)網(wǎng)的發(fā)展催生了跨域訪問的需求,各種跨域方法和協(xié)議滿足了需求但也增加了各種風(fēng)險。尤其是XSS和CSRF等攻擊的盛行也得益于此。

了解這些技術(shù)背景有助于在實(shí)際項(xiàng)目中熟練應(yīng)用并規(guī)避各種安全風(fēng)險。

Reference

[1] 白帽子講Web安全: http://chabaoo.cn/books/164067.html
[2] 使用 JSONP 實(shí)現(xiàn)跨域通信: http://www.ibm.com/developerworks/cn/web/wa-aj-jsonp1/
[3] Cross-origin resource sharing: http://en.wikipedia.org/wiki/Cross-Origin_Resource_Sharing
[4] Cross-domain policy for Flash movies: http://kb2.adobe.com/cps/142/tn_14213.html

更多關(guān)于JavaScript相關(guān)內(nèi)容可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript切換特效與技巧總結(jié)》、《JavaScript查找算法技巧總結(jié)》、《JavaScript錯誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)

希望本文所述對大家JavaScript程序設(shè)計有所幫助。

相關(guān)文章

  • uniapp實(shí)現(xiàn)微信一鍵登錄按鈕樣式(膠囊按鈕的樣式)

    uniapp實(shí)現(xiàn)微信一鍵登錄按鈕樣式(膠囊按鈕的樣式)

    這篇文章主要介紹了uniapp實(shí)現(xiàn)微信一鍵登錄按鈕樣式,如何開發(fā)膠囊按鈕的樣式,需要的朋友可以參考下
    2024-07-07
  • 小程序視頻列表中視頻的播放與停止的示例代碼

    小程序視頻列表中視頻的播放與停止的示例代碼

    本篇文章主要介紹了小程序視頻列表中視頻的播放與停止的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • JavaScript實(shí)現(xiàn)點(diǎn)擊按鈕直接打印

    JavaScript實(shí)現(xiàn)點(diǎn)擊按鈕直接打印

    很多網(wǎng)站都有此功能,當(dāng)瀏覽到底部時都會有一個打印按鈕,點(diǎn)擊打印按鈕就可以完成打印功能,功能非常不錯,人性化,下面通過本文給大家介紹JavaScript實(shí)現(xiàn)點(diǎn)擊按鈕就打印的代碼,需要的朋友參考下
    2016-01-01
  • 微信小程序+騰訊地圖開發(fā)實(shí)現(xiàn)路徑規(guī)劃繪制

    微信小程序+騰訊地圖開發(fā)實(shí)現(xiàn)路徑規(guī)劃繪制

    這篇文章主要介紹了微信小程序+騰訊地圖開發(fā)實(shí)現(xiàn)路徑規(guī)劃繪制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • js彈性勢能動畫之拋物線運(yùn)動實(shí)例詳解

    js彈性勢能動畫之拋物線運(yùn)動實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹了js彈性勢能動畫之拋物線運(yùn)動的制作方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • JavaScript模板引擎實(shí)現(xiàn)原理實(shí)例詳解

    JavaScript模板引擎實(shí)現(xiàn)原理實(shí)例詳解

    這篇文章主要介紹了JavaScript模板引擎實(shí)現(xiàn)原理,結(jié)合實(shí)例形式詳細(xì)分析了JavaScript模板引擎原理、定義、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2018-12-12
  • 小程序?qū)崿F(xiàn)購物車完整版

    小程序?qū)崿F(xiàn)購物車完整版

    這篇文章主要為大家詳細(xì)介紹了小程序?qū)崿F(xiàn)購物車完整版,實(shí)現(xiàn)加減計算數(shù)量跟金額,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • echartjs實(shí)現(xiàn)cross十星輔助線實(shí)現(xiàn)示例詳解

    echartjs實(shí)現(xiàn)cross十星輔助線實(shí)現(xiàn)示例詳解

    這篇文章主要為大家介紹了echartjs實(shí)現(xiàn)cross十星輔助線實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • antd?table長表格出現(xiàn)滾動條的操作方法

    antd?table長表格出現(xiàn)滾動條的操作方法

    這篇文章主要介紹了antd?table長表格如何出現(xiàn)滾動條,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • js實(shí)現(xiàn)簡單放大鏡特效

    js實(shí)現(xiàn)簡單放大鏡特效

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)簡單放大鏡特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03

最新評論