<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    The NoteBook of EricKong

      BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
      611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

    在客戶(hù)端編程語(yǔ)言中,如JavaScript和ActionScript,同源策略是一個(gè)很重要的安全理念,它在保證數(shù)據(jù)的安全性方面有著重要的意義。同 源策略規(guī)定跨域之間的腳本是隔離的,一個(gè)域的腳本不能訪(fǎng)問(wèn)和操作另外一個(gè)域的絕大部分屬性和方法。那么什么叫相同域,什么叫不同的域呢?

    同源策略

    在客戶(hù)端編程語(yǔ)言中,如JavaScript和ActionScript,同源策略是一個(gè)很重要的安全理念,它在保證數(shù)據(jù)的安全性方面有著重要的意義。同源策略規(guī)定跨域之間的腳本是隔離的,一個(gè)域的腳本不能訪(fǎng)問(wèn)和操作另外一個(gè)域的絕大部分屬性和方法

    那么什么叫相同域,什么叫不同的域呢?當(dāng)兩個(gè)域具有相同的協(xié)議(如http), 相同的端口(如80),相同的host(如www.example.org),那么我們就可以認(rèn)為它們是相同的域。比如http://www.example.org/和http://www.example.org/sub/是同域,而http://www.example.org, https://www.example.org, http://www.example.org:8080, http://sub.example.org中的任何兩個(gè)都將構(gòu)成跨域。同源策略還應(yīng)該對(duì)一些特殊情況做處理,比如限制file協(xié)議下腳本的訪(fǎng)問(wèn)權(quán)限。本地的HTML文件在瀏覽器中是通過(guò)file協(xié)議打開(kāi)的,如果腳本能通過(guò)file協(xié)議訪(fǎng)問(wèn)到硬盤(pán)上其它任意文件,就會(huì)出現(xiàn)安全隱患,目前IE8還有這樣的隱患。

    受到同源策略的影響,跨域資源共享就會(huì)受到制約。但是隨著人們的實(shí)踐和瀏覽器的進(jìn)步,目前在跨域請(qǐng)求的技巧上,有很多寶貴經(jīng)驗(yàn)的沉淀和積累。這里我把跨域資源共享分成兩種,一種是單向的數(shù)據(jù)請(qǐng)求,還有一種是雙向的消息通信。接下來(lái)我將羅列出常見(jiàn)的一些跨域方式,以下跨域?qū)嵗脑创a可以從這里獲得。

    單向跨域

    JSONP

    JSONP (JSON with Padding)是一個(gè)簡(jiǎn)單高效的跨域方式,HTML中的script標(biāo)簽可以加載并執(zhí)行其他域的JavaScript,于是我們可以通過(guò)script標(biāo)記來(lái)動(dòng)態(tài)加載其他域的資源。例如我要從域A的頁(yè)面pageA加載域B的數(shù)據(jù),那么在域B的頁(yè)面pageB中我以JavaScript的形式聲明pageA需要的數(shù)據(jù),然后在pageA中用script標(biāo)簽把pageB加載進(jìn)來(lái),那么pageB中的腳本就會(huì)得以執(zhí)行。JSONP在此基礎(chǔ)上加入了回調(diào)函數(shù),pageB加載完之后會(huì)執(zhí)行pageA中定義的函數(shù),所需要的數(shù)據(jù)會(huì)以參數(shù)的形式傳遞給該函數(shù)。JSONP易于實(shí)現(xiàn),但是也會(huì)存在一些安全隱患,如果第三方的腳本隨意地執(zhí)行,那么它就可以篡改頁(yè)面內(nèi)容,截獲敏感數(shù)據(jù)。但是在受信任的雙方傳遞數(shù)據(jù),JSONP是非常合適的選擇。

    Flash URLLoader

    Flash有自己的一套安全策略,服務(wù)器可以通過(guò)crossdomain.xml文件來(lái)聲明能被哪些域的SWF文件訪(fǎng)問(wèn),SWF也可以通過(guò)API來(lái)確定自身能被哪些域的SWF加載。當(dāng)跨域訪(fǎng)問(wèn)資源時(shí),例如從域www.a.com請(qǐng)求域www.b.com上的數(shù)據(jù),我們可以借助Flash來(lái)發(fā)送HTTP請(qǐng)求。首先,修改域www.b.com上的crossdomain.xml(一般存放在根目錄,如果沒(méi)有需要手動(dòng)創(chuàng)建) ,把www.a.com加入到白名單。其次,通過(guò)Flash URLLoader發(fā)送HTTP請(qǐng)求,最后,通過(guò)Flash API把響應(yīng)結(jié)果傳遞給JavaScript。Flash URLLoader是一種很普遍的跨域解決方案,不過(guò)需要支持iOS的話(huà),這個(gè)方案就無(wú)能為力了。

    Access Control

    Access Control是比較超越的跨域方式,目前只在很少的瀏覽器中得以支持,這些瀏覽器可以發(fā)送一個(gè)跨域的HTTP請(qǐng)求(Firefox, Google Chrome等通過(guò)XMLHTTPRequest實(shí)現(xiàn),IE8下通過(guò)XDomainRequest實(shí)現(xiàn)),請(qǐng)求的響應(yīng)必須包含一個(gè)Access-Control-Allow-Origin的HTTP響應(yīng)頭,該響應(yīng)頭聲明了請(qǐng)求域的可訪(fǎng)問(wèn)權(quán)限。例如www.a.com對(duì)www.b.com下的asset.php發(fā)送了一個(gè)跨域的HTTP請(qǐng)求,那么asset.php必須加入如下的響應(yīng)頭:

    header("Access-Control-Allow-Origin: http://www.a.com"); 		

    window.name

    window對(duì)象的name屬性是一個(gè)很特別的屬性,當(dāng)該window的location變化,然后重新加載,它的name屬性可以依然保持不變。那么我們可以在頁(yè)面A中用iframe加載其他域的頁(yè)面B,而頁(yè)面B中用JavaScript把需要傳遞的數(shù)據(jù)賦值給window.name,iframe加載完成之后,頁(yè)面A修改iframe的地址,將其變成同域的一個(gè)地址,然后就可以讀出window.name的值了。這個(gè)方式非常適合單向的數(shù)據(jù)請(qǐng)求,而且協(xié)議簡(jiǎn)單、安全。不會(huì)像JSONP那樣不做限制地執(zhí)行外部腳本。

    server proxy

    在數(shù)據(jù)提供方?jīng)]有提供對(duì)JSONP協(xié)議或者window.name協(xié)議的支持,也沒(méi)有對(duì)其它域開(kāi)放訪(fǎng)問(wèn)權(quán)限時(shí),我們可以通過(guò)server proxy的方式來(lái)抓取數(shù)據(jù)。例如當(dāng)www.a.com域下的頁(yè)面需要請(qǐng)求www.b.com下的資源文件asset.txt時(shí),直接發(fā)送一個(gè)指向www.b.com/asset.txt的ajax請(qǐng)求肯定是會(huì)被瀏覽器阻止。這時(shí),我們?cè)趙ww.a.com下配一個(gè)代理,然后把a(bǔ)jax請(qǐng)求綁定到這個(gè)代理路徑下,例如www.a.com/proxy/, 然后這個(gè)代理發(fā)送HTTP請(qǐng)求訪(fǎng)問(wèn)www.b.com下的asset.txt,跨域的HTTP請(qǐng)求是在服務(wù)器端進(jìn)行的,客戶(hù)端并沒(méi)有產(chǎn)生跨域的ajax請(qǐng)求。這個(gè)跨域方式不需要和目標(biāo)資源簽訂協(xié)議,帶有侵略性,另外需要注意的是實(shí)踐中應(yīng)該對(duì)這個(gè)代理實(shí)施一定程度的保護(hù),比如限制他人使用或者使用頻率。

    雙向跨域

    document.domain

    通過(guò)修改document的domain屬性,我們可以在域和子域或者不同的子域之間通信。同域策略認(rèn)為域和子域隸屬于不同的域,比如www.a.com和sub.a.com是不同的域,這時(shí),我們無(wú)法在www.a.com下的頁(yè)面中調(diào)用sub.a.com中定義的JavaScript方法。但是當(dāng)我們把它們document的domain屬性都修改為a.com,瀏覽器就會(huì)認(rèn)為它們處于同一個(gè)域下,那么我們就可以互相調(diào)用對(duì)方的method來(lái)通信了。

    FIM – Fragment Identitier Messaging

    不同的域之間,JavaScript只能做很有限的訪(fǎng)問(wèn)和操作,其實(shí)我們利用這些有限的訪(fǎng)問(wèn)權(quán)限就可以達(dá)到跨域通信的目的了。FIM (Fragment Identitier Messaging)就是在這個(gè)大前提下被發(fā)明的。父窗口可以對(duì)iframe進(jìn)行URL讀寫(xiě),iframe也可以讀寫(xiě)父窗口的URL,URL有一部分被稱(chēng)為frag,就是#號(hào)及其后面的字符,它一般用于瀏覽器錨點(diǎn)定位,Server端并不關(guān)心這部分,應(yīng)該說(shuō)HTTP請(qǐng)求過(guò)程中不會(huì)攜帶frag,所以這部分的修改不會(huì)產(chǎn)生HTTP請(qǐng)求,但是會(huì)產(chǎn)生瀏覽器歷史記錄。FIM的原理就是改變URL的frag部分來(lái)進(jìn)行雙向通信。每個(gè)window通過(guò)改變其他window的location來(lái)發(fā)送消息,并通過(guò)監(jiān)聽(tīng)自己的URL的變化來(lái)接收消息。這個(gè)方式的通信會(huì)造成一些不必要的瀏覽器歷史記錄,而且有些瀏覽器不支持onhashchange事件,需要輪詢(xún)來(lái)獲知URL的改變,最后,URL在瀏覽器下有長(zhǎng)度限制,這個(gè)制約了每次傳送的數(shù)據(jù)量。

    Flash LocalConnection

    頁(yè)面上的雙向通信也可以通過(guò)Flash來(lái)解決,F(xiàn)lash API中有LocalConnection這個(gè)類(lèi),該類(lèi)允許兩個(gè)SWF之間通過(guò)進(jìn)程通信,這時(shí)SWF可以播放在獨(dú)立的Flash Player或者AIR中,也可以嵌在HTML頁(yè)面或者是PDF中。遵循這個(gè)通信原則,我們可以在不同域的HTML頁(yè)面各自嵌套一個(gè)SWF來(lái)達(dá)到相互傳遞數(shù)據(jù)的目的了。SWF通過(guò)LocalConnection交換數(shù)據(jù)是很快的,但是每次的數(shù)據(jù)量有40kb的大小限制。用這種方式來(lái)跨域通信過(guò)于復(fù)雜,而且需要了2個(gè)SWF文件,實(shí)用性不強(qiáng)。

    window.postMessage

    window.postMessage是HTML5定義的一個(gè)很新的方法,這個(gè)方法可以很方便地跨window通信。由于它是一個(gè)很新的方法,所以在很舊和比較舊的瀏覽器中都無(wú)法使用。

    Cross Frame

    Cross Frame是FIM的一個(gè)變種,它借助了一個(gè)空白的iframe,不會(huì)產(chǎn)生多余的瀏覽器歷史記錄,也不需要輪詢(xún)URL的改變,在可用性和性能上都做了很大的改觀(guān)。它的基本原理大致是這樣的,假設(shè)在域www.a.com上有頁(yè)面A.html和一個(gè)空白代理頁(yè)面proxyA.html, 另一個(gè)域www.b.com上有個(gè)頁(yè)面B.html和一個(gè)空白代理頁(yè)面proxyB.html,A.html需要向B.html中發(fā)送消息時(shí),頁(yè)面會(huì)創(chuàng)建一個(gè)隱藏的iframe, iframe的src指向proxyB.html并把message作為URL frag,由于B.html和proxyB.html是同域,所以在iframe加載完成之后,B.html可以獲得iframe的URL,然后解析出message,并移除該iframe。當(dāng)B.html需要向A.html發(fā)送消息時(shí),原理一樣。Cross Frame是很好的雙向通信方式,而且安全高效,但是它在Opera中無(wú)法使用,不過(guò)在Opera下面我們可以使用更簡(jiǎn)單的window.postMessage來(lái)代替。

    總結(jié)

    跨域的方法很多,不同的應(yīng)用場(chǎng)景我們都可以找到一個(gè)最合適的解決方案。比如單向的數(shù)據(jù)請(qǐng)求,我們應(yīng)該優(yōu)先選擇JSONP或者window.name,雙向通信我們采取Cross Frame,在未與數(shù)據(jù)提供方?jīng)]有達(dá)成通信協(xié)議的情況下我們也可以用server proxy的方式來(lái)抓取數(shù)據(jù)。

    posted on 2013-10-08 13:13 Eric_jiang 閱讀(280) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JavaScript
    主站蜘蛛池模板: 成人免费毛片内射美女-百度| 热久久精品免费视频| 日本高清免费网站| 久久亚洲中文字幕精品一区四| 亚洲综合久久久久久中文字幕| 无码天堂va亚洲va在线va| 无码国产精品一区二区免费式芒果| 在线播放免费播放av片| 亚洲色自偷自拍另类小说| 亚洲粉嫩美白在线| 在线免费观看h片| 最新69国产成人精品免费视频动漫 | 亚洲高清无码综合性爱视频| 亚洲成在人线中文字幕| 一级毛片人与动免费观看| 久久久高清免费视频| 亚洲熟妇丰满多毛XXXX| 亚洲AV无码一区二区三区久久精品| 久久永久免费人妻精品| 免费在线观看理论片| 亚洲免费一级视频| 韩国免费A级毛片久久| 女人与禽交视频免费看| 亚洲AV日韩精品久久久久| 黄网站色视频免费看无下截| 亚洲免费视频观看| 久久九九亚洲精品| 成人在线免费视频| 丁香花在线观看免费观看| 久久亚洲精品中文字幕无码| 阿v免费在线观看| 免费网站看v片在线香蕉| 亚洲国产精品久久久久秋霞影院| 中国毛片免费观看| 免费国产成人午夜电影| 亚洲精品一二三区| 真人做A免费观看| 亚洲精品综合一二三区在线| 国产成人无码精品久久久免费| 国产精品久免费的黄网站| 亚洲五月综合网色九月色|