跨域問題

前后端數(shù)據(jù)交互經(jīng)常會(huì)碰到請(qǐng)求跨域植锉,什么是跨域辫樱,以及有哪幾種跨域方式,這是本文要探討的內(nèi)容俊庇。

一狮暑、什么是跨域?

廣義上講辉饱,跨域是指一個(gè)域下的文檔或者腳本試圖請(qǐng)求另一個(gè)域下的資源心例。例如:

1)資源跳轉(zhuǎn):重定向、表單提交鞋囊。
2)資源嵌入:<link>止后、<script>、<img>溜腐、<frame>等dom標(biāo)簽译株,還有樣式中background:url()、@font-face()等文件外鏈挺益。
3)腳本請(qǐng)求: js發(fā)起的ajax請(qǐng)求歉糜、dom和js對(duì)象的跨域操作等。

通常我們說的跨域是狹義的望众,是由瀏覽器同源策略限制的一類請(qǐng)求場(chǎng)景匪补。“同源策略/SOP(Same origin policy)”是一種約定烂翰,它是瀏覽器最核心也是最基礎(chǔ)的安全功能夯缺,如果沒有“同源策略”,瀏覽器很容易受到XSS,CSFR等攻擊甘耿。所謂同源是指:

協(xié)議+域名+端口 三者相同踊兜,即便兩個(gè)不同域名指向同一個(gè)ip地址,也非同源佳恬。

二 捏境、常見跨域場(chǎng)景

常見跨域場(chǎng)景

特別說明兩點(diǎn):
1) 如果是協(xié)議和端口造成的跨域問題于游,前臺(tái)界面是無能為力的。
2)跨域問題上垫言,僅僅是通過URL的首部來識(shí)別而不會(huì)根據(jù)域名對(duì)應(yīng)的ip地址是否相同來判斷贰剥。URL的首部可以理解成協(xié)議,域名和端口必須匹配筷频。

三蚌成、跨域請(qǐng)求,請(qǐng)求完成了嗎截驮?

跨域并不是請(qǐng)求發(fā)不出去笑陈,請(qǐng)求能發(fā)出去际度,服務(wù)端能收到請(qǐng)求并正常返回結(jié)果葵袭,只是結(jié)果被瀏覽器攔截了。你可能會(huì)疑問明明通過表單的方式可以發(fā)起跨域請(qǐng)求乖菱,為什么 Ajax 就不會(huì)?因?yàn)闅w根結(jié)底坡锡,跨域是為了阻止用戶讀取到另一個(gè)域名下的內(nèi)容,Ajax 可以獲取響應(yīng)窒所,瀏覽器認(rèn)為這不安全鹉勒,所以攔截了響應(yīng)。但是表單并不會(huì)獲取新的內(nèi)容吵取,所以可以發(fā)起跨域請(qǐng)求禽额。同時(shí)也說明了跨域并不能完全阻止 CSRF,因?yàn)檎?qǐng)求畢竟是發(fā)出去了皮官。

四脯倒、跨域解決方案

1) 通過jsonp跨域
通常為了減輕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馍佑,再請(qǐng)求一個(gè)帶參網(wǎng)址實(shí)現(xiàn)跨域通信斋否。
利用 <script> 標(biāo)簽沒有跨域限制的漏洞,網(wǎng)頁可以得到從其他來源動(dòng)態(tài)產(chǎn)生的 JSON 數(shù)據(jù)拭荤。JSONP請(qǐng)求一定需要對(duì)方的服務(wù)器做支持才可以如叼。

1.1)原生實(shí)現(xiàn):

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

    // 傳參一個(gè)回調(diào)函數(shù)名給后端,方便后端返回時(shí)執(zhí)行這個(gè)在前端定義的回調(diào)函數(shù)
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);

    // 回調(diào)執(zhí)行函數(shù)
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>
服務(wù)端返回如下(返回時(shí)即執(zhí)行全局函數(shù)):

handleCallback({"status": true, "user": "admin"})

1.2)jquery ajax實(shí)現(xiàn):

$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 請(qǐng)求方式為jsonp
    jsonpCallback: "handleCallback",    // 自定義回調(diào)函數(shù)名
    data: {}
});

1.3)vue.js實(shí)現(xiàn):

this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

1.4) 后端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...');

1.5) JSONP優(yōu)缺點(diǎn):
JSONP優(yōu)點(diǎn)是簡單兼容性好穷劈,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題笼恰。缺點(diǎn)是僅支持get方法具有局限性,不安全可能會(huì)遭受XSS攻擊踊沸。
2)跨域資源共享(CORS)

跨域資源共享標(biāo)準(zhǔn)新增了一組 HTTP 首部字段,允許服務(wù)器聲明哪些源站通過瀏覽器有權(quán)限訪問哪些資源社证。另外逼龟,規(guī)范要求,對(duì)那些可能對(duì)服務(wù)器數(shù)據(jù)產(chǎn)生副作用的 HTTP 請(qǐng)求方法追葡,瀏覽器必須首先使用 HTTP 的 OPTIONS 方法 用于獲取目的資源所支持的通信選項(xiàng)腺律。客戶端可以對(duì)特定的 URL 使用 OPTIONS 方法宜肉,也可以對(duì)整站(通過將 URL 設(shè)置為“*”)使用該方法匀钧。") 方法發(fā)起一個(gè)預(yù)檢請(qǐng)求(preflight request),從而獲知服務(wù)端是否允許該跨域請(qǐng)求谬返。服務(wù)器確認(rèn)允許之后之斯,才發(fā)起實(shí)際的 HTTP 請(qǐng)求。在預(yù)檢請(qǐng)求的返回中遣铝,服務(wù)器端也可以通知客戶端佑刷,是否需要攜帶身份憑證(包括 Cookies 和 HTTP 認(rèn)證相關(guān)數(shù)據(jù))。

五酿炸、總結(jié)

CORS支持所有類型的HTTP請(qǐng)求瘫絮,是跨域HTTP請(qǐng)求的根本解決方案
JSONP只支持GET請(qǐng)求,JSONP的優(yōu)勢(shì)在于支持老式瀏覽器填硕,以及可以向不支持CORS的網(wǎng)站請(qǐng)求數(shù)據(jù)麦萤。
不管是Node中間件代理還是nginx反向代理,主要是通過同源策略對(duì)服務(wù)器不加限制扁眯。
日常工作中壮莹,用得比較多的跨域方案是cors和nginx反向代理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末恋拍,一起剝皮案震驚了整個(gè)濱河市垛孔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌施敢,老刑警劉巖周荐,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異僵娃,居然都是意外死亡概作,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門默怨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讯榕,“玉大人,你說我怎么就攤上這事∮奁ǎ” “怎么了济竹?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長霎槐。 經(jīng)常有香客問我送浊,道長,這世上最難降的妖魔是什么丘跌? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任袭景,我火速辦了婚禮,結(jié)果婚禮上闭树,老公的妹妹穿的比我還像新娘耸棒。我一直安慰自己,他們只是感情好报辱,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布与殃。 她就那樣靜靜地躺著,像睡著了一般捏肢。 火紅的嫁衣襯著肌膚如雪奈籽。 梳的紋絲不亂的頭發(fā)上饥侵,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天鸵赫,我揣著相機(jī)與錄音,去河邊找鬼躏升。 笑死辩棒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的膨疏。 我是一名探鬼主播一睁,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼佃却!你這毒婦竟也來了者吁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤饲帅,失蹤者是張志新(化名)和其女友劉穎复凳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灶泵,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡育八,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赦邻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片髓棋。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出按声,到底是詐尸還是另有隱情膳犹,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布签则,位于F島的核電站镣奋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏怀愧。R本人自食惡果不足惜侨颈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芯义。 院中可真熱鬧哈垢,春花似錦、人聲如沸扛拨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绑警。三九已至求泰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間计盒,已是汗流浹背渴频。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留北启,地道東北人卜朗。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像咕村,于是被迫代替她去往敵國和親场钉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

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

  • 瀏覽器在請(qǐng)求不同域的資源時(shí),會(huì)因?yàn)橥床呗缘挠绊懻?qǐng)求不成功批钠,這就是通常被提到的“跨域問題”宇植。作為前端開發(fā),解決跨域...
    SCQ000閱讀 2,559評(píng)論 1 52
  • 跨域問題的場(chǎng)景和解決方案多種多樣价匠,只要是做前端開發(fā)当纱,總會(huì)遇到。而且面試時(shí)也是必問的問題踩窖。所以自己學(xué)習(xí)總結(jié)記錄一下坡氯。...
    花開_陳鳳娟閱讀 737評(píng)論 0 0
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛箫柳,但實(shí)際上跨域的范圍絕對(duì)不止那么狹隘手形。具體概念如下:只要協(xié)議...
    他在發(fā)呆閱讀 824評(píng)論 0 0
  • http://www.ruanyifeng.com/blog/2016/04/cors.htmlCORS是一個(gè)W3...
    文茶君閱讀 202評(píng)論 0 0
  • 做過 web 開發(fā)的同學(xué),應(yīng)該都遇到過跨域的問題悯恍,當(dāng)我們從一個(gè)域名向另一個(gè)域名發(fā)送 Ajax 請(qǐng)求的時(shí)候库糠,打開瀏覽...
    強(qiáng)哥科技興閱讀 447評(píng)論 0 1