Web - JSONP和同源策略漫談


0x00 前言

關於JSONP網上有很多文章了,我也是在拜讀了別人的文章的基礎上來寫寫自己的看法,這樣可以加深自己印象,鞏固一下學習效果。我們需要做的就是站在巨人的肩膀上眺望遠方。

0x01 起

在Web前端開發中有一種安全機制,Javascript腳本只能訪問與它同域的內容,這就是同源策略。
這里就需要先說明一個問題:如果確定腳本的域?

html頁面中試用腳本有兩種方式:內聯和引用。

上圖中滑紅框部分,src為引用方式,直接在script中寫代碼是內聯方式。
如果html的頁面url為:http://a.huangjacky.com/a.html,那么內聯方式腳本的域是a.huangjacky.com,這應該比較容易理解。
引用方式有兩種情況,引用的js文件就是A站點、引用的js是其他站點,但是不過是內聯還是引用方式的腳本代碼它執行都是在當前html下,因此它的域是和html相同的

圖中例子用的是AJAX網絡請求,其實Javascript訪問內容還可以DOM操作,當iframe之間的域不相同時,也無法通過Javascript去操作其他iframe中的DOM元素。

上面這個還比較基礎,老鳥別噴。

現在開始我們的例子:

  1. 有兩個站點a.huangjacky.com, b.huangjacky.com
  2. A站點的a.html要去請求B站點的b.php

a.html的代碼如上圖,b.php的代碼如下:

1 <?php
2 echo"from b site";

我們點擊a.html中按鈕看一下會是什么樣的效果?


提示說的很清楚,A站的Javascript的XMLHttpRequest對象無法加載B站,因為沒有Access-Control-Allow-Origin頭,那么接下來我們就來看看這個HTTP頭有什么用?

在跨域HTTP請求中,會有一個HTTP頭叫Origin,上圖中也可以看出來,響應中HTTP頭中的Access-Control-Allow-Origin包含Origin域,那么就滿足跨域,瀏覽器就不會報錯了,接下來我們修改PHP代碼:

1 <?php
2 header("Access-Control-Allow-Origin: http://a.huangjacky.com");
3 echo"from b site"

代碼中就增加一行header設置,看看運行效果:

運行正常了,AJAX也獲得到了B站數據了,但是如果有個C站也要獲取B站數據呢?我們分別嘗試設置Access-Control-Allow-Orgin為http://huangjacky.comhttp://*.huangjacky.com。都出現了通源策略訪問錯誤的提示,我這里就不截圖了,我肯定是試了的。

現在問題出來了,我就是有這樣的需求,多個子域都要訪問B站來獲取數據,怎么辦?

其實這里可以設置Access-Control-Allow-Orgin: * ,就可以了。

但是這樣安全性又是一個問題了,所有的網站都可以訪問來訪問數據了,而Access-Control-Allow-Orgin頭要么是*,要么指定子域名。其實這里我們可以在PHP中做一些邏輯判斷,比如判斷Origin頭是否huangjacky.com的請求,那么就設置Access-Control-Allow-Orgin為*,不就可以了么?代碼如下:

1 <?php
2 $origin = $_SERVER['HTTP_ORIGIN'];
3 if(preg_match('/^http:\/\/\w+\.huangjacky\.com/i',$origin))
4     header("Access-Control-Allow-Origin: *");
5 echo"from b site";

具體其他的參數可以參考附錄中的詳細文檔咯。

0x02 承

JSONP也是Web開發中針對跨域提出來一種方法,它不是新技術,反而是一些老技術的整合,這樣在瀏覽器的兼容性上面做得不錯。前面我們說到過script標簽的src是可以跨域引用js,把js加載到自己的域中來執行。因此我們可以在引用js的同時提交一些參數,這樣B站根據參數做出相應的操作后,將操作的結果寫入到js文件中,並返回給A站點,這樣A站點就得到了B站點的數據了。

第一框中function是A站在加載完B站數據后執行的函數。第二框是一個DOM中添加一個script標簽。因此我們現在有必要看看B站后台是怎么實現的:

重點是要輸出要確定Content-Type,然后就是拼湊javascript代碼了。

是吧很簡單的,在jQuery在$.ajax函數中將參數dataType設置成jsonp的話,就會按照這種原理來實現跨域,和XMLHttpRequest沒有半毛錢的關系了。

0x03 轉

從JSONP的原理來看的話,script標簽只能GET方式。還有就是后台程序需要對callback參數進行有效性過濾,不然惡意用戶可以插入攻擊代碼了。一般使用正則:

^[a-z0-9_]+$

來判斷用戶的回調函數名是否合法。

而JSONP中經常還會遇到一個問題就是JSON劫持,這是CSRF中的一種,常用的防御方式都是部署TOKEN。

0x04 附錄

  1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
  2. http://www.ibm.com/developerworks/cn/web/wa-aj-jsonp1/
  3. http://www.nowamagic.net/librarys/veda/detail/224

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM