天天看點

Web安全之同源政策與跨域通路一、怎樣才算是同源二、IE特例三、讀寫權限四、同源政策示例五、跨域通路資源六、參考

古語雲:“無規矩不成方圓”。同源政策(

Same origin policy

)是一種約定,它是浏覽器最核心也最基本的安全功能,如果缺少了同源政策,則浏覽器的正常功能可能都會受到影響。可以說Web是建構在同源政策基礎之上的,浏覽器隻是針對同源政策的一種實作。

一、怎樣才算是同源

所謂同源是指域名(主機名或者IP位址)、端口、協定相同。不同的用戶端腳本(

JavaScript

ActionScript

)在沒明确授權的情況下,不能讀取對方的資源。

不同源的例子:

1. 域名(主機名或者IP位址)不同

http://news.company.com/index.html

http://www.company.com/index.html

不同源,域名不同,

news

子域與

www

子域不同。

http://company.com/index.html

http://www.company.com/index.html

不同源,域名不同,頂級域與

www

子域不是一個概念。

2. 端口不同

http://www.company.com:8080/index.html

http://www.company.com/index.html

不同源,端口不同,

8080

與預設的

80

端口不同。

3. 協定不同

https://www.company.com/index.html

http://www.company.com/index.html

不同源,協定不同,

https

http

是不同協定。

同源的例子:

http://www.company.com/a/c/index.html

http://www.company.com/b/d/index.html

屬于同源,域名,端口,協定均相同。

二、IE特例

在處理同源政策的問題上,IE存在兩個主要的不同之處。

1. 授權範圍(Trust Zones)

兩個互相之間高度互信的域名,如公司域名(corporate domains),不遵守同源政策的限制。

2. 端口

IE并沒有将端口号加入到同源政策的組成部分之中,是以,

https://www.company.com/index.html

http://www.company.com/index.html

屬于同源并且不受任何限制。

這些例外都是非标準的,其他也并未作出支援

三、讀寫權限

Web上的資源有很多,有的隻有讀權限,有的同時擁有讀和寫的權限。比如:HTTP請求頭裡的Referer(表示請求來源)隻可讀,同源和不同源就是根據這個Referer值進行判斷的, 而

document.cookie

則具備讀寫權限。這樣的區分也是為了安全上的考慮。

注意:

Cookie

中的同源隻關注域名,忽略協定和端口。是以

https://localhost:8080/

http://localhost:8081/

Cookie

是共享的。

四、同源政策示例

如果是打開百度,在控制台中請求CSDN的網頁的話,會報下面的異常:

Chrome

中會報下面的異常:

Web安全之同源政策與跨域通路一、怎樣才算是同源二、IE特例三、讀寫權限四、同源政策示例五、跨域通路資源六、參考

IE

中會報下面的異常:

Web安全之同源政策與跨域通路一、怎樣才算是同源二、IE特例三、讀寫權限四、同源政策示例五、跨域通路資源六、參考

五、跨域通路資源

1. Ajax跨域(

CORS

)

Ajax

主要是通過

XMLHttpRequest

對象與遠端的伺服器進行資訊互動的。但是

XMLHttpRequest

受到同源政策的限制,不能跨域通路資源。

如果

XMLHttpRequest

能夠跨域通路資源,則會導緻安全問題。因為

XMLHttpRequest

是一個純粹的

JavaScript

對象,如果某網站存在漏洞導緻

XSS

注入了

JavaScript

腳本,這個腳本就可以通過

Ajax

擷取使用者的資訊并通過

Ajax

送出到其他站點。

但是

XMLHttpRequest

可以通過通路目标域的伺服器,然後目标域的伺服器傳回的HTTP響應頭來授權是否允許跨域通路,假如目标站點

http://www.foo.com

傳回的響應頭如下:

Access-Control-Allow-Origin: http://www.evil.com

那麼

www.evil.com

站點上的用戶端腳本就有權通過

Ajax

技術對

www.foo.com

上的資料進行讀寫操作。

請求及響應過程如下:

Web安全之同源政策與跨域通路一、怎樣才算是同源二、IE特例三、讀寫權限四、同源政策示例五、跨域通路資源六、參考

通過在

HTTP Header

中加入擴充字段,伺服器在相應網頁頭部加入字段表示允許通路的

domain

HTTP method

,用戶端檢查自己的域是否在允許清單中,決定是否處理響應。

實作的基礎是

JavaScript

不能夠操作

HTTP Header

。某些浏覽器插件實際上是具有這個能力的。

伺服器端在

HTTP

的響應頭中加入(頁面層次的控制模式):

Access-Control-Allow-Origin: evil.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: 
           

多個域名之間用逗号分隔,表示對所示域名提供跨域通路權限。”*”表示允許所有域名的跨域通路。

用戶端可以有兩種行為:

1. 發送

OPTIONS

請求,請求

Access-Control

資訊。如果自己的域名在允許的通路清單中,則發送真正的請求,否則放棄請求發送。

2. 直接發送請求,然後檢查

response

Access-Control

資訊,如果自己的域名在允許的通路清單中,則讀取

response body

,否則放棄。

本質上服務端的

response

内容已經到達本地,

JavaScript

決定是否要去讀取。

Support: [Javascript Web Applications]

* IE >= 8 (需要安裝caveat)

* Firefox >= 3

* Safari 完全支援

* Chrome 完全支援

* Opera 不支援

CORS

協定提升了

Ajax

的跨域能力,但也增加了風險。一旦網站被注入腳本或

XSS

攻擊,将非常友善的擷取使用者資訊并悄悄傳遞出去。

2. Jsonp實作跨域通路請求(單向跨域)

JSONP

(

JSON with Padding

)是一個簡單高效的跨域方式,

HTML

中的

script

标簽可以加載并執行其他域的

JavaScript

,于是我們可以通過

script

标記來動态加載其他域的資源。例如我要從域A的頁面

pageA

加載域B的資料,那麼在域B的頁面

pageB

中我以

JavaScript

的形式聲明

pageA

需要的資料,然後在

pageA

中用

script

标簽把

pageB

加載進來,那麼

pageB

中的腳本就會得以執行。

JSONP

在此基礎上加入了回調函數,

pageB

加載完之後會執行

pageA

中定義的函數,所需要的資料會以參數的形式傳遞給該函數。

第一個站點的測試頁面(

http://localhost:8080/test.html

):
<script src="http://localhost:8081/test_data.js" type="text/javascript"></script> 
<script>
   function test_handler(data) { 
        console.log(data);  
   }  
</script> 
           
伺服器端的

Javascript

腳(

http://localhost:8081/test_data.js

):
test_handler('{"data": "something"}');
           
為了動态實作

JSONP

請求,可以使用

Javascript

動态插入

<script>

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

JSONP

協定封裝了上述步驟,

jQuery

中統一實作在

Ajax

中(其中

data type

JSONP

):

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

為了支援

JSONP

協定,伺服器端必須提供特别的支援,另外

JSONP

隻支援

GET

請求。

利用

jQuery

中的

Ajax

實作

jsonp

跨域請求可以檢視我之前的部落格

JavaScript實作百度搜尋suggestion功能

3. document.domain(雙向跨域)

通過修改

document

domain

屬性,我們可以在域和子域或者不同的子域之間通信。同域政策認為域和子域隸屬于不同的域,比如

www.a.com

sub.a.com

是不同的域,這時,我們無法在

www.a.com

下的頁面中調用

sub.a.com

中定義的

JavaScrip

t方法。但是當我們把它們

document

domain

屬性都修改為

a.com

,浏覽器就會認為它們處于同一個域下,那麼我們就可以互相調用對方的

method

來通信了。

注意:浏覽器單獨儲存端口号。任何的指派操作,包括

document.domain

=

document.domain

都會以

null

值覆寫掉原來的端口号。是以

company.com:8080

頁面的腳本不能僅通過設定

document.domain

=

"company.com"

就能與

company.com

通信。指派時必須帶上端口号,以確定端口号不會為

null

。另外,使用

document.domain

來安全是讓子域通路其父域,需要同時将子域和父域的

document.domain

設定為相同的值。必須要這麼做,即使是簡單的将父域設定為其原來的值。沒有這麼做的話可能導緻授權錯誤。

4. window.postMessage(雙向跨域)

window.postMessage

HTML5

定義的一個很新的方法,這個方法可以很友善地跨

window

通信。由于它是一個很新的方法,是以在很舊和比較舊的浏覽器中都無法使用。

例如:
targetWindow.postMessage(data, origin);
           
1

.data

:要傳遞的資料,

html5

規範中提到該參數可以是

JavaScript

的任意基本類型或可複制的對象,然而并不是所有浏覽器都做到了這點兒,部分浏覽器隻能處理字元串參數,是以我們在傳遞參數的時候需要使用

JSON.stringify()

方法對對象參數序列化,在低版本IE中引用

json2.js

可以實作類似效果。

2.

origin

:字元串參數,指明目标視窗的源,協定+主機+端口号[+URL],

URL

會被忽略,是以可以不寫,這個參數是為了安全考慮,

postMessage()

方法隻會将

message

傳遞給指定視窗,當然如果願意也可以建參數設定為”*”,這樣可以傳遞給任意視窗,如果要指定和目前視窗同源的話設定為”/”。

接收消息:

window.addEventListener('message', handler, false);
           

handler

event.data

postMessage

發送來的資料,

event.origin

是發送視窗的

origin

event.source

是發送消息的視窗引用

5. 跨域内嵌的資源

a.

<script src="..."></script>

标簽嵌入跨域腳本。文法錯誤資訊隻能在同源腳本中捕捉到

b.

<link rel="stylesheet" href="..." target="_blank" rel="external nofollow" >

标簽嵌入

CSS

c.

<img>

嵌入圖檔。支援的圖檔格式包括

PNG

,

JPEG

,

GIF

,

BMP

,

SVG

,…

d.

<video>

<audio>

嵌入多媒體資源。

e.

<object>

,

<embed>

<applet>

的插件。

f.

@font-face

引入的字型。一些浏覽器允許跨域字型( cross-origin fonts),一些需要同源字型(same-origin fonts)。

g.

<frame>

<iframe>

載入的任何資源。站點可以使用X-Frame-Options消息頭來阻止這種形式的跨域互動。

六、參考

1. 百度百科:同源政策

2. JavaScript 的同源政策

3. 浏覽器的同源政策

4. 跨域資源共享的10種方式

5. 同源政策和跨域通路

繼續閱讀