利用<script>標簽沒有跨域限制的漏洞。
為什么會有同源限制呢措左?
沒有同源(同協(xié)議、同域名怎披、同端口)策略胸嘁,就天下大亂了凉逛。
如果沒有同源策略,不同源的數(shù)據和資源(如HTTP頭鱼炒、Cookie、DOM昔瞧、localStorage等)就能相互隨意訪問,根本沒有隱私和安全可言自晰。為了安全起見和資源的有效管理,瀏覽器當然要采用這種策略酬荞。
一個重要原因就是對cookie的保護
cookie 中存著sessionID 。黑客一旦獲取了sessionID 并且在有效期內 就可以登錄
這里我們可以簡單的認為sessionID 全等于 賬戶加密碼
想想當我們訪問了一個惡意網站 如果沒有同源策略 那么這個網站就能通過js 訪問document.cookie 得到用戶關于的各個網站的sessionID 其中可能有銀行網站http://qq.comgithub blabla....
通過已經建立好的session連接進行攻擊的 這里有一個專有名詞 美名曰 CSRF 攻擊 題主可以去查 還有需要注意的是同源策略無法完全防御CSRF 這里需要服務端配合
什么是JSONP混巧?
首先提一下JSON這個概念,JSON是一種輕量級的數(shù)據傳輸格式咧党,被廣泛應用于當前Web應用中。JSON格式數(shù)據的編碼和解析基本在所有主流語言中都被實現(xiàn)傍衡,所以現(xiàn)在大部分前后端分離的架構都以JSON格式進行數(shù)據的傳輸。
那么JSONP是什么呢蛙埂?
首先拋出瀏覽器同源策略這個概念,為了保證用戶訪問的安全叠赐,現(xiàn)代瀏覽器使用了同源策略被辑,即不允許訪問非同源的頁面。這里大家只要知道谈山,在ajax中宏怔,不允許請求非同源的URL就可以了畴椰,比如www.a.com下的一個頁面鸽粉,其中的ajax請求是不允許訪問www.b.com/c.php這樣一個頁面的。
JSONP就是用來解決跨域請求問題的帚戳,那么具體是怎么實現(xiàn)的呢儡首?
JSONP原理
首先,因為ajax無法跨域对供,然后開發(fā)者就有所思考
其次氛濒,開發(fā)者發(fā)現(xiàn), 標簽的src屬性是可以跨域的
把跨域服務器寫成 調用本地的函數(shù) 舞竿,回調數(shù)據回來不就好了炬灭?
json剛好被js支持(object)
調用跨域服務器上動態(tài)生成的js格式文件(不管是什么類型的地址靡菇,最終生成的返回值都是一段js代碼)
這種獲取遠程數(shù)據的方式看起來非常像ajax,但其實并不一樣
便于客戶端使用數(shù)據厦凤,逐漸形成了一種非正式傳輸協(xié)議较鼓,人們把它稱作JSONP。
傳遞一個callback參數(shù)給跨域服務端博烂,然后跨域服務端返回數(shù)據時會將這個callback參數(shù)作為函數(shù)名來包裹住json數(shù)據即可。
例子
【栗子一】
文件:remote.js
代碼:
alert('我是遠程文件');
本地:
<script type="text/javascript" src="跨域服務器/remote.js"></script>
這邊做的就是直接引入一個js畜伐,頁面將會彈出一個提示窗體躺率,顯示 我是遠程文件。
【栗子二】
跨域服務器
文件:remote.js
代碼:
localHandler({"result":"我是遠程js帶來的數(shù)據"});
本地
<script type="text/javascript">
var localHandler = function(data){
alert('我是本地函數(shù)慎框,可以被跨域的remote.js文件調用,遠程js帶來的數(shù)據是:' + data.result);
};
</script>
<script type="text/javascript" src="跨域服務器/remote.js"></script>
這邊做的是
1薪丁、本地定義一個函數(shù)
2馅精、引入一個js
3、被引入的js里面阻问,調用這個函數(shù)
頁面將會彈出一個提示窗體沦疾。顯示本地函數(shù)被跨域的遠程js調用成功,并且還接收到了 我是遠程js帶來的數(shù)據刨秆。
新問題出現(xiàn)了:讓遠程js知道它應該調用的本地函數(shù)叫什么名字呢忆畅?畢竟是jsonp的服務者都要面對很多服務對象,而這些服務對象各自的本地函數(shù)都不相同盎捍住绊诲?
【栗子三】
跨域服務端提供的js腳本動態(tài)生成,這樣調用者可以傳一個參數(shù)過去告訴跨域服務端“我想要一段調用XXX函數(shù)的js代碼掂之,請你返回給我”世舰,于是跨域服務器就可以按照客戶端的需求來生成js腳本并響應了。
跨域服務器
文件:flightResult.php
代碼:
flightHandler({
"code":"CA1998",
"price": 1780,
"tickets": 5
});
本地
<script type="text/javascript">
// 得到航班信息查詢結果后的回調函數(shù)
var flightHandler = function(data){
alert('你查詢的航班結果是:票價 ' + data.price + ' 元胰蝠,' + '余票 ' + data.tickets + ' 張。');
};
// 提供jsonp服務的url地址(不管是什么類型的地址姊氓,最終生成的返回值都是一段javascript代碼)
var url = "跨域服務器/flightResult.php?code=CA1998&callback=flightHandler";
// 創(chuàng)建script標簽翔横,設置其屬性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script標簽加入head,此時調用開始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
這次我們做的是
1禾唁、動態(tài)創(chuàng)建腳本
2荡短、url中傳遞了一個code參數(shù),服務器去做查詢CA1998次航班的信息掘托,callback參數(shù)告訴服務器,我的本地回調函數(shù)叫做flightHandler
3弯院、跨域服務端調用這個函數(shù)flightHandler 頁面將會彈出一個提示窗體泪掀。把票價、余票以及張數(shù)給傳遞回來了椅挣。
那么服務器到底做了什么呢塔拳? 說到底,就是拼接字符串名惩。
// 數(shù)據
$data = [
"name":"anonymous66",
"age":"18",
"like":"jianshu"
];
// 接收callback函數(shù)名稱
$callback = $_GET['callback'];
// 輸出
echo $callback . "(" . json_encode($data) . ")";
與AJAX的區(qū)別是什么孕荠?
ajax和jsonp本質上是不同的東西攻谁。
ajax的核心是通過XmlHttpRequest獲取非本頁內容
jsonp的核心則是動態(tài)添加<script>標簽來調用服務器提供的js腳本。