深入淺析同源與跨域,jsonp(函數(shù)封裝),CORS原理
同源政策
Ajax請(qǐng)求限制:
Ajax 只能向自己的服務(wù)器發(fā)送請(qǐng)求
同源策略是瀏覽器的一個(gè)安全功能,不同源的客戶端腳本在沒有明確授權(quán)的情況下,不能讀寫對(duì)方資源。
比如現(xiàn)在有一個(gè)A網(wǎng)站、有一個(gè)B網(wǎng)站,A網(wǎng)站中的 HTML 文件只能向A網(wǎng)站服務(wù)器中發(fā)送 Ajax 請(qǐng)求,
B網(wǎng)站中的 HTML 文件只向 B 網(wǎng)站中發(fā)送 Ajax 請(qǐng)求,但是 A 網(wǎng)站是不能向 B 網(wǎng)站發(fā)送 Ajax請(qǐng)求的,
同理,B 網(wǎng)站也不能向 A 網(wǎng)站發(fā)送 Ajax請(qǐng)求。
同源:
如果兩個(gè)頁面擁有相同的協(xié)議、域名和端口,那么這兩個(gè)頁面就屬于同一個(gè)源,其中只要有一個(gè)不相同,就是不同源。
http://www.example.com/dir/page.html
- http://www.example.com/dir2/other.html:同源
- http://example.com/dir/other.html:不同源(域名不同)
- http://v2.www.example.com/dir/other.html:不同源(域名不同)
- http://www.example.com:81/dir/other.html:不同源(端口不同)
- https://www.example.com/dir/page.html:不同源(協(xié)議不同)
同源政策的目的:
- 同源政策是為了保證用戶信息的安全,防止惡意的網(wǎng)站竊取數(shù)據(jù)。最初的同源政策是指 A 網(wǎng)站在客戶端設(shè)置的 Cookie,B網(wǎng)站是不能訪問的。
- 隨著互聯(lián)網(wǎng)的發(fā)展,同源政策也越來越嚴(yán)格,在不同源的情況下,其中有一項(xiàng)規(guī)定就是無法向非同源地址發(fā)送Ajax 請(qǐng)求,如果請(qǐng)求,瀏覽器就會(huì)報(bào)錯(cuò)。
不受同源策略限制:
頁面中的鏈接,重定向以及表單提交是不會(huì)受到同源策略限制的跨域資源的引入是可以的。但是js不能讀寫加載的內(nèi)容。如嵌入到頁面中的<script src="..."></script>
,<img>
,<link>
,<iframe>
等
跨域問題
跨域:只要協(xié)議、域名、端口號(hào)有一個(gè)不同就是跨域
跨域的原因:
跨域問題 來源于 JavaScript的同源策略,即只有 協(xié)議+主機(jī)名+端口號(hào)(如存在)相同,則允許相互訪問。
為了防止某域名下的接口被其他域名下的網(wǎng)頁非法調(diào)用,是瀏覽器對(duì)JavaScript施加的安全限制。
也就是說JavaScript只能訪問和操作自己域下的資源,不能訪問和操作其他域下的資源。
跨域問題是針對(duì) JS 和 Ajax 的, html 本身沒有跨域問題,
比如a標(biāo)簽、script標(biāo)簽、甚至form標(biāo)簽(可以直接跨域發(fā)送數(shù)據(jù)并接收數(shù)據(jù)) 等
解決跨域問題:
JSONP
:利用script標(biāo)簽可跨域的特點(diǎn),在跨域腳本中可以直接回調(diào)當(dāng)前腳本的函數(shù)。
CORS
:服務(wù)器設(shè)置HTTP響應(yīng)頭中Access-Control-Allow-Origin
值,解除跨域限制。 注意:這兩個(gè)跨域方案都存在一個(gè)致命的缺陷,嚴(yán)重依賴后端的協(xié)助。
反向代理(Reverse Proxy
):前端獨(dú)立就能解決的跨域方案:
指以 代理服務(wù)器 來接受internet上的連接請(qǐng)求,
然后將請(qǐng)求轉(zhuǎn)發(fā)給內(nèi)部網(wǎng)絡(luò)上的服務(wù)器,
并將從服務(wù)器上得到的結(jié)果返回給internet上請(qǐng)求連接的客戶端,
此時(shí)代理服務(wù)器對(duì)外就表現(xiàn)為一個(gè)反向代理服務(wù)器。
JSONP
使用 JSONP 解決
jsonp 是 JSON with padding(填充式 JSON 或參數(shù)式 JSON)的簡寫,它 不屬于 Ajax 請(qǐng)求,但它可以 模擬 Ajax 請(qǐng)求
JSONP 由兩部分組成:回調(diào)函數(shù)和數(shù)據(jù)
- 回調(diào)函數(shù)是當(dāng)響應(yīng)到來時(shí)應(yīng)該在頁面中調(diào)用的函數(shù)?;卣{(diào)函數(shù)的名字一般是在請(qǐng)求中指定的。
- 數(shù)據(jù)就是傳入回調(diào)函數(shù)中的 JSON 數(shù)據(jù)。
解決方法:
簡單理解:在服務(wù)器端將json數(shù)據(jù)作為函數(shù)參數(shù),填充到函數(shù)當(dāng)中,在客戶端中調(diào)用函數(shù)從而對(duì)數(shù)據(jù)進(jìn)行處理
JSONP實(shí)現(xiàn)跨域請(qǐng)求的原理簡單的說,就是動(dòng)態(tài)創(chuàng)建<script>
標(biāo)簽,然后利用<script>
的 src 不受同源策略約束來跨域獲取數(shù)據(jù)。
JSONP的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
不像XMLHttpRequest對(duì)象實(shí)現(xiàn)的Ajax請(qǐng)求那樣受到同源策略的限制兼容性更好,在更加古老的瀏覽器中都可以運(yùn)行,
不需要XMLHttpRequest或ActiveX的支持并且在請(qǐng)求完畢后可以通過調(diào)用callback的方式回傳結(jié)果
缺點(diǎn):
只支持GET請(qǐng)求而不支持POST等其它類型的HTTP請(qǐng)求只支持跨域HTTP請(qǐng)求這種情況,
不能解決不同域的兩個(gè)頁面之間如何進(jìn)行JavaScript調(diào)用的問題
JSONP代碼優(yōu)化:
客戶端需要將函數(shù)名稱傳遞到服務(wù)器端
將 script 請(qǐng)求的發(fā)送變成動(dòng)態(tài)請(qǐng)求
封裝 jsonp 函數(shù),方便請(qǐng)求發(fā)送
服務(wù)器端代碼優(yōu)化之res.jsonp 方法
JSONP函數(shù)封裝:
function jsonp (options) { // 動(dòng)態(tài)創(chuàng)建script標(biāo)簽 var script = document.createElement('script'); // 拼接字符串的變量 var params = ''; for (var attr in options.data) { params += '&' + attr + '=' + options.data[attr]; } // myJsonp0124741 var fnName = 'myJsonp' + Math.random().toString().replace('.', ''); // 將它變成全局函數(shù) window[fnName] = options.success; // 為script標(biāo)簽添加src屬性 script.src = options.url + '?callback=' + fnName + params; // 將script標(biāo)簽追加到頁面中 document.body.appendChild(script); // 為script標(biāo)簽添加onload事件 script.onload = function () { document.body.removeChild(script); } }
使用:
// 獲取按鈕 var btn1 = document.getElementById('btn1'); var btn2 = document.getElementById('btn2'); // 為按鈕添加點(diǎn)擊事件 btn1.onclick = function () { jsonp({ // 請(qǐng)求地址 url: 'http://localhost:3001/better', data: { name: 'lisi', age: 30 }, success: function (data) { console.log(123) console.log(data) } }) } btn2.onclick = function () { jsonp({ // 請(qǐng)求地址 url: 'http://localhost:3001/better', success: function (data) { console.log(456789) console.log(data) } }) }
CORS
使用CORS解決
CORS:全稱為 Cross-origin resource sharing,即跨域資源共享,它允許瀏覽器向跨域服務(wù)器發(fā)送 Ajax 請(qǐng)求,克服了 Ajax 只能同源使用的限制。
//設(shè)置服務(wù)器的響應(yīng)頭信息,實(shí)現(xiàn)跨域 res.setHeader("Access-Control-Allow-Origin", "*"); /* 星號(hào)表示所有的域都可以接受, */
Express框架中跨域的實(shí)現(xiàn):
安裝跨域模塊:語法: npm install cors
在app.js文件中引入cors模塊:var cors = require('cors')
使用跨域模塊(在app.js文件中) :app.use(cors())
以上就是深入淺析同源與跨域,jsonp(函數(shù)封裝),CORS原理的詳細(xì)內(nèi)容,更多關(guān)于同源與跨域,jsonp(函數(shù)封裝),CORS的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js解析與序列化json數(shù)據(jù)(一)json.stringify()的基本用法
對(duì)象有兩個(gè)方法:stringify()和parse()。在最簡單的情況下,這兩個(gè)方法分別用于把JavaScript對(duì)象序列化為JSON字符串和把JSON字符串解析為原生JavaScript2013-02-02Ajax+Json 級(jí)聯(lián)菜單實(shí)現(xiàn)代碼
Ajax+Json 級(jí)聯(lián)菜單實(shí)現(xiàn)代碼,需要的朋友可以參考下。2009-10-10詳解JSON1:使用TSQL查詢數(shù)據(jù)和更新JSON數(shù)據(jù)
這篇文章主要介紹了使用TSQL查詢數(shù)據(jù)和更新JSON數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-11-11nodejs教程 安裝express及配置app.js文件的詳細(xì)步驟
express.js是nodejs的一個(gè)MVC開發(fā)框架,并且支持jade等多種模板。下面簡單來說說express的安裝和app.js文件的配置,然后在今后的教程中一步一步使用express.js搭建個(gè)聊天室2013-05-05javascript 循環(huán)讀取JSON數(shù)據(jù)的代碼
服務(wù)端向客戶端返回了一串JSON格式的數(shù)據(jù)。在有些時(shí)候,因?yàn)槟承┨厥獾脑蛭覀儾恢涝嫉膋ey值,因此我們此時(shí)無法象正常一樣通過key值,來獲取value值。這時(shí)我們必須循環(huán)讀取JSON對(duì)象數(shù)據(jù)。廢話少說,來看例子。2010-07-07用nodejs寫的一個(gè)簡單項(xiàng)目打包工具
項(xiàng)目是模塊加載的,類似require.js的用法,所以簡單寫了一個(gè)js打包工具2013-05-05