JSONP_跨域

什么是同源策略

同源策略/SOP(Same origin policy)是一種約定岛抄,由Netscape公司1995年引入瀏覽器绅络,它是瀏覽器最核心也最基本的安全功能月培,如果缺少了同源策略嘁字,瀏覽器很容易受到XSS、CSFR等攻擊杉畜。

所謂同源是指"協(xié)議+域名+端口" 三者相同纪蜒,即便兩個(gè)不同的域名指向同一個(gè)ip地址,也非同源此叠。

同源策略限制以下幾種行為:

1.) Cookie纯续、LocalStorage 和 IndexDB 無法讀取
2.) DOM 和 Js對象無法獲得
3.) AJAX 請求不能發(fā)送

本域指的是

例子

不同源的例子:

需要注意的是: 對于當(dāng)前頁面來說頁面存放的 JS 文件的域不重要灭袁,重要的是加載該 JS 頁面所在什么域

什么是跨域猬错?跨域有幾種實(shí)現(xiàn)形式

廣義的跨域:

  1. 資源跳轉(zhuǎn): A鏈接、重定向茸歧、表單提交
  2. 資源嵌入:<link>倦炒、<script>、<img>软瞎、<frame>等dom標(biāo)簽逢唤,還有樣式中background:url()、@font-face()等文件外鏈
  3. 腳本請求: js發(fā)起的ajax請求涤浇、dom和js對象的跨域操作等

其實(shí)我們通常所說的跨域是狹義的智玻,是由瀏覽器同源策略限制的一類請求場景。

跨域解決方案

  1. 通過jsonp跨域
  2. document.domain + iframe跨域(降域)
  3. location.hash + iframe
  4. window.name + iframe跨域
  5. postMessage跨域
  6. 跨域資源共享(CORS)
  7. nginx代理跨域
  8. nodejs中間件代理跨域
  9. WebSocket協(xié)議跨域

1. JSONP

簡易例子

請求方:frank.com的前端程序員(瀏覽器)
響應(yīng)方:jack.com的后端程序員(服務(wù)器)

  1. 請求方創(chuàng)建 script芙代,src指向響應(yīng)方,同時(shí)傳一個(gè)查詢參數(shù) ?callbackName=xxx
  2. 響應(yīng)方根據(jù)查詢參數(shù)callbackName,構(gòu)造形如
    1. xxx.call(undefined,'所需的數(shù)據(jù)')
    2. xxx('所需的數(shù)據(jù)')
  3. 瀏覽器接收到相應(yīng)盖彭,就會(huì)執(zhí)行xxx.call(undefined,'所需的數(shù)據(jù)')
  4. 那么請求方就知道他所需要的數(shù)據(jù)
js
服務(wù)器

query為temp.query,提取請求URL中的哈希值

約定

  1. callbackName 一般用 callback
  2. xxx 一般用 隨機(jī)數(shù) 例如jq1253156(數(shù)值隨機(jī)纹烹,避免函數(shù)名重復(fù))

通常為了減輕web服務(wù)器的負(fù)載,我們把js召边、css铺呵,img等靜態(tài)資源分離到另一臺(tái)獨(dú)立域名的服務(wù)器上,在html頁面中再通過相應(yīng)的標(biāo)簽從不同域名下加載靜態(tài)資源隧熙,而被瀏覽器允許片挂,基于此原理,我們可以通過動(dòng)態(tài)創(chuàng)建script贞盯,再請求一個(gè)帶參網(wǎng)址實(shí)現(xiàn)跨域通信音念。
jsonp缺點(diǎn):只能實(shí)現(xiàn)get一種請求。

步驟

  1. 定義數(shù)據(jù)處理函數(shù)onBack()
  2. 創(chuàng)建script標(biāo)簽躏敢,src的地址執(zhí)行后端接口闷愤,最后加個(gè)參數(shù)callback=onBack
  3. 服務(wù)端在收到請求后,解析參數(shù)件余,計(jì)算返還數(shù)據(jù)讥脐,輸出 onBack(date)字符串遭居。
  4. onBack(date)會(huì)放到script標(biāo)簽做為js執(zhí)行。此時(shí)會(huì)調(diào)用onBack函數(shù)旬渠,將data做為參數(shù)俱萍。

JSONP為何不支持POST??

  1. 因?yàn)镴SONP是通過動(dòng)態(tài)創(chuàng)建script實(shí)現(xiàn)
  2. script無法支持POST

詳細(xì)

<script>元素的src屬性設(shè)成一個(gè)回傳JSON的URL是可以想像的,這也代表從HTML頁面通過script元素抓取 JSON是可能的告丢。

然而枪蘑,一份JSON文件并不是一個(gè)JavaScript程序。為了讓瀏覽器可以在<script>元素運(yùn)行芋齿,從src里URL 回傳的必須是可運(yùn)行的JavaScript腥寇。在JSONP的使用模式里,該URL回傳的是由函數(shù)調(diào)用包起來的動(dòng)態(tài)生成JSON觅捆,這就是JSONP的“填充(padding)”或是“前輟(prefix)”的由來赦役。

慣例上瀏覽器提供回調(diào)函數(shù)的名稱當(dāng)作送至服務(wù)器的請求中命名查詢參數(shù)的一部分衫哥,例如:

 <script>
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // 傳參并指定回調(diào)執(zhí)行函數(shù)為onBack
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
    document.head.appendChild(script);

    // 回調(diào)執(zhí)行函數(shù)
    function onBack(res) {
        alert(JSON.stringify(res));
    }
 </script>

服務(wù)器會(huì)在傳給瀏覽器前將JSON數(shù)據(jù)填充到回調(diào)函數(shù)(onBack)中其骄。瀏覽器得到的回應(yīng)已不是單純的數(shù)據(jù)敘述而是一個(gè)腳本探橱。在本例中屁柏,瀏覽器得到的是:

onBack({"Name": "小明", "Id" : 1823, "Rank": 7})

后端node.js代碼示例:

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();

server.on('request', function(req, res) {
    var params = qs.parse(req.url.split('?')[1]);
    var fn = params.callback;

    // jsonp返回設(shè)置
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    res.write(fn + '(' + JSON.stringify(params) + ')');

    res.end();
});

server.listen('8080');
console.log('Server is running at port 8080...');

2. CORS

CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing)跟啤,是一種 ajax 跨域請求資源的方式赊时,支持現(xiàn)代瀏覽器吕粗,IE支持10以上互婿。
實(shí)現(xiàn)方式很簡單释移,當(dāng)你使用 XMLHttpRequest 發(fā)送請求時(shí)叭披,瀏覽器發(fā)現(xiàn)該請求不符合同源策略,會(huì)給該請求加一個(gè)請求頭:Origin玩讳,后臺(tái)進(jìn)行一系列處理涩蜘,如果確定接受請求則在返回結(jié)果中加入一個(gè)響應(yīng)頭:Access-Control-Allow-Origin; 瀏覽器判斷該相應(yīng)頭中是否包含 Origin 的值,如果有則瀏覽器會(huì)處理響應(yīng)熏纯,我們就可以拿到響應(yīng)數(shù)據(jù)同诫,如果不包含瀏覽器直接駁回,這時(shí)我們無法拿到響應(yīng)數(shù)據(jù)樟澜。
所以 CORS 的表象是讓你覺得它與同源的 ajax 請求沒啥區(qū)別误窖,代碼完全一樣。

此方法的原理是:

  1. 在服務(wù)器上添加下面語句秩贰,告訴瀏覽器霹俺,除了同源網(wǎng)址外,還接收什么網(wǎng)址訪問
res.header("Access-Control-Allow-Origin", "http://a.jrg.com:8080");   
//允許http://a.jrg.com:8080 端口訪問
res.header("Access-Control-Allow-Origin", "*");    //允許所有其他端口訪問

3. 降域

例如有a(a.jinrengu.com)毒费、b(b.jinrengu.com)兩個(gè)網(wǎng)址吭服,現(xiàn)在需要用a訪問b網(wǎng)址,由于兩個(gè)網(wǎng)址不一樣蝗罗,故不同源艇棕,瀏覽器阻止訪問b網(wǎng)址蝌戒。
此方案僅限主域相同,子域不同的跨域應(yīng)用場景沼琉。
原理:實(shí)現(xiàn)原理:兩個(gè)頁面都通過js強(qiáng)制設(shè)置document.domain為基礎(chǔ)主域北苟,就實(shí)現(xiàn)了同域。
1.)父窗口:(http://a.yuanqianyi.com:8080/a.html)

<html>
<style>
  .ct{
    width: 910px;
    margin: auto;
  }
  .main{
    float: left;
    width: 450px;
    height: 300px;
    border: 1px solid #ccc;
  }
  .main input{
    margin: 20px;
    width: 200px;
  }
  .iframe{
    float: right;
  }

  iframe{
    width: 450px;
    height: 300px;
    border: 1px dashed #ccc;
  }
</style>

<div class="ct">
  <h1>使用降域?qū)崿F(xiàn)跨域</h1>
  <div class="main">
    <input type="text" placeholder="http://a.yuanqianyi.com:8080/a.html">
  </div>

  <iframe src="http://b.yuanqianyi.com:8080/b.html" frameborder="0" ></iframe>

</div>


<script>

document.querySelector('.main input').addEventListener('input', function(){
  console.log(this.value);
  window.frames[0].document.querySelector('input').value = this.value;
})
document.domain = "yuanqianyi.com"

</script>


</html>

2.)子窗口:(http://b.yuanqianyi.com:8080/b.html)

<html>
<style>
    html,body{
        margin: 0;
    }
    input{
        margin: 20px;
        width: 200px;
    }


</style>
    哇哇哇哇
    <input id="input" type="text"  placeholder="http://b.yuanqianyi.com:8080/b.html">
<script>

document.querySelector('#input').addEventListener('input', function(){
    window.parent.document.querySelector('input').value = this.value;
})

document.domain = 'yuanqianyi.com';

</script>



</html>

4. postMessage跨域

postMessage是HTML5 XMLHttpRequest Level 2中的API打瘪,且是為數(shù)不多可以跨域操作的window屬性之一友鼻,它可用于解決以下方面的問題:

  1. 頁面和其打開的新窗口的數(shù)據(jù)傳遞
  2. 多窗口之間消息傳遞
  3. 頁面與嵌套的iframe消息傳遞
  4. 上面三個(gè)場景的跨域數(shù)據(jù)傳遞
  • 用法:postMessage(data,origin)方法接受兩個(gè)參數(shù)
  • data: html5規(guī)范支持任意基本類型或可復(fù)制的對象,但部分瀏覽器只支持字符串闺骚,所以傳參時(shí)最好用JSON.stringify()序列化彩扔。
  • origin: 協(xié)議+主機(jī)+端口號(hào),也可以設(shè)置為"*"僻爽,表示可以傳遞給任意窗口虫碉,如果要指定和當(dāng)前窗口同源的話設(shè)置為"/"。
  1. a.html: (http://a.yuanqianyi.com:8080/a.html)
//向b發(fā)送跨域請求
document.querySelector('.main input').addEventListener('input', function(){
    console.log(this.value)
    window.frames[0].postMessage(this.value,"*")
})
//接收b返回的數(shù)據(jù)
window.addEventListener("message",function(e){
    document.querySelector('.main input').value = e.data
    console.log(e.data)
})


  1. b.html:(http://b.yuanqianyi.com:8080/b.html)
// 接收a的數(shù)據(jù)請求
window.addEventListener("message",function(e){
    document.querySelector('input').value = e.data
    console.log(e.data)
})

//發(fā)送數(shù)據(jù)給a
document.querySelector('input').addEventListener('input', function(){
    window.parent.postMessage(this.value,"*")
    window.parent.document.querySelector('input').value = this.value;
})

參考1
參考2

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胸梆,一起剝皮案震驚了整個(gè)濱河市敦捧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碰镜,老刑警劉巖兢卵,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绪颖,居然都是意外死亡秽荤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門柠横,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窃款,“玉大人,你說我怎么就攤上這事滓鸠。” “怎么了第喳?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵糜俗,是天一觀的道長。 經(jīng)常有香客問我曲饱,道長悠抹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任扩淀,我火速辦了婚禮楔敌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驻谆。我一直安慰自己卵凑,他們只是感情好庆聘,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勺卢,像睡著了一般伙判。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上黑忱,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天宴抚,我揣著相機(jī)與錄音,去河邊找鬼甫煞。 笑死菇曲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抚吠。 我是一名探鬼主播常潮,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼埃跷!你這毒婦竟也來了蕊玷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤弥雹,失蹤者是張志新(化名)和其女友劉穎垃帅,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剪勿,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贸诚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厕吉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酱固。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖头朱,靈堂內(nèi)的尸體忽然破棺而出运悲,到底是詐尸還是另有隱情,我是刑警寧澤项钮,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布班眯,位于F島的核電站,受9級特大地震影響烁巫,放射性物質(zhì)發(fā)生泄漏署隘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一亚隙、第九天 我趴在偏房一處隱蔽的房頂上張望磁餐。 院中可真熱鬧,春花似錦阿弃、人聲如沸诊霹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畅哑。三九已至肴楷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荠呐,已是汗流浹背赛蔫。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留泥张,地道東北人呵恢。 一個(gè)月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像媚创,于是被迫代替她去往敵國和親渗钉。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 什么是同源策略? 同源是瀏覽器出于安全方面的考慮钞钙,只允許與本域下的接口交互鳄橘。不同源的客戶端腳本在沒有明確授權(quán)的情況...
    YM雨蒙閱讀 339評論 1 4
  • 題目1: 什么是同源策略 瀏覽器出于安全方面考慮,只允許與本域下的接口交互芒炼。不同源的客戶端腳本在沒有明確授權(quán)的情況...
    Taaaaaaaurus閱讀 204評論 0 0
  • 題目1: 什么是同源策略 瀏覽器出于安全方面的考慮瘫怜,只允許與本域下的接口交互。不同源的客戶端腳本在沒有明確授權(quán)的情...
    無目的閱讀 255評論 0 0
  • 官方文檔翻譯本刽,官方鏈接鲸湃。翻譯水平有限,且以學(xué)習(xí)為主子寓,請諒解和提意見暗挑。轉(zhuǎn)載請注明出處!P庇选炸裆! 管理命令 現(xiàn)在HA的Na...
    mikeliuy閱讀 299評論 0 0
  • 加粗為原文。 古敘利亞和古印度的宗教天才都在國外的新地方得到了充分發(fā)展鲜屏,并最終開花結(jié)果——這證明了“先知只在本鄉(xiāng)本...
    b0b48da4f6e6閱讀 411評論 0 1