阿里P7架構(gòu)師是如何解決跨域問(wèn)題的!你有遇到嗎萨咳?

現(xiàn)在越來(lái)越多的項(xiàng)目就算是一個(gè)管理后端也偏向于使用前后端分離的部署方式去做,為了順應(yīng)時(shí)代的潮流疫稿,一前后端分離就產(chǎn)生了跨域問(wèn)題培他,所以許多同學(xué)把跨域和前后端分離項(xiàng)目聯(lián)系在了一起,其實(shí)跨域產(chǎn)生的原因并不是前后端分離導(dǎo)致的遗座,那我們一起來(lái)看一下舀凛,希望可以靠這一篇文章解答大家所有的跨域問(wèn)題

一、跨域產(chǎn)生的條件

  • 使用xmlHttpRequest,即我們通常說(shuō)的ajax請(qǐng)求
  • 瀏覽器做了這個(gè)事
  • 訪問(wèn)的域名不同途蒋,即訪問(wèn)的html頁(yè)面是a域名下的猛遍,但內(nèi)部js發(fā)送的ajax請(qǐng)求的目標(biāo)地址卻是b域名

以上三個(gè)條件缺一不可,尤其是第三個(gè)條件許多做移動(dòng)端的同學(xué)可能都沒有聽過(guò)号坡,因?yàn)橐苿?dòng)端爽爽的用各種http請(qǐng)求狂發(fā)不同的域名懊烤,但是瀏覽器不允許我們這么做,為了一個(gè)詞安全

二宽堆、如何解決跨域問(wèn)題

解決跨域問(wèn)題的根本就是要打破上述的三個(gè)限制中的任何一個(gè)腌紧,我們來(lái)看一下逐個(gè)擊破的方式

JSONP方式

jsonp是打破第一重限制,用了XMLHttpRequest就跨域畜隶,那我不用這種方式了壁肋,我們?cè)趺醋龅模瑏?lái)看一段jquery的帶jsonp的ajax請(qǐng)求

$.ajax({
   type : "GET",
   url : "http://api.map.baidu.com/geocoder/v2/",
   data:"address=上海",
   dataType:"jsonp",
   jsonp:"callback",
   jsonpCallback:"showLocation",
   success : function(data){
       alert("成功");
   },
   error : function(data){
       alert("失敗");
   }
});

看似用了ajax請(qǐng)求籽慢,其實(shí)內(nèi)部完全不是那么回事浸遗,多了jsonp和jsonpCallback選項(xiàng),它內(nèi)部將代碼翻譯并把頁(yè)面上的dom操作成這樣

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script type='text/javascript'>
      // 后端返回直接執(zhí)行的方法箱亿,相當(dāng)于執(zhí)行這個(gè)方法跛锌,由于后端把返回的數(shù)據(jù)放在方法的參數(shù)里,所以這里能拿到res届惋。
      window.showLocation = function (res) {
        console.log(res)
        //執(zhí)行ajax回調(diào)
      }
    </script>
    <script src='http://api.map.baidu.com/geocoder/v2/?address=上海&callback=showLocation' type='text/javascript'></script>
  </body>
</html>

這個(gè)時(shí)候察净,html頁(yè)面的script src標(biāo)簽回去訪問(wèn)api.map.baidu.com的服務(wù)端,由于script盼樟,img這種標(biāo)簽瀏覽器是不受xmlhttprequest限制的氢卡,可以隨意訪問(wèn),這個(gè)時(shí)候?qū)?yīng)的后端代碼取得address參數(shù)晨缴,最后根據(jù)雙方約定好的callback參數(shù)译秦,返回一個(gè)被包裝后的json,即

showLocation({
    status: 0,
    result: {
        location: {
            lng: 121.4219317908279,
            lat: 31.361653367912695
        },
        precise: 1,
        confidence: 80,
        comprehension: 99,
        level: "道路"
    }
})

然后瀏覽器直接執(zhí)行了對(duì)應(yīng)的這個(gè)showLocation()… 等等,這個(gè)不就相當(dāng)于執(zhí)行了我們上面定義的window.showLocation方法并且傳入了我們需要的json返回嗎筑悴,那我們的ajax success方法里就可以得到這個(gè)返回類型了们拙,并且沒有跨域,是不是很精妙阁吝。

CORS

CORS是一個(gè)W3C標(biāo)準(zhǔn)砚婆,全稱是"跨域資源共享"(Cross-origin resource sharing)跨域資源共享 CORS 詳解。這個(gè)玩樣用于“破解”掉瀏覽器的限制突勇,說(shuō)是破解其實(shí)也是瀏覽器認(rèn)識(shí)到了一些頭部就放行了的意思装盯,需要在http的response內(nèi)多設(shè)置幾個(gè)頭部

  • Access-Control-Allow-Origin:* 表明允許所有的origin(瀏覽器的html頁(yè)面路徑)訪問(wèn),而并非是同源的origin
  • Access-Control-Request-Method:* 表明允許所有的http request頭甲馋,訪問(wèn)埂奈,因?yàn)闉g覽器在觸發(fā)如下幾個(gè)場(chǎng)景會(huì)在發(fā)送真正的數(shù)據(jù)前發(fā)送options這樣的預(yù)檢請(qǐng)求檢測(cè),一旦預(yù)檢通過(guò)后才會(huì)發(fā)送真正的get或post數(shù)據(jù)請(qǐng)求定躏,這個(gè)時(shí)候我們按照cors的設(shè)置就需要允許對(duì)應(yīng)的method訪問(wèn)账磺,觸發(fā)的幾種情況包括
    1:請(qǐng)求的方法不是GET/HEAD/POST
    2:POST請(qǐng)求的Content-Type并非application/x-www-form-urlencoded, multipart/form-data, 或text/plain
    3:請(qǐng)求設(shè)置了自定義的header字段等
  • Access-Control-Allow-Headers:* 設(shè)置所有header均可以被允許,這個(gè)配置聯(lián)通上述的request method options檢測(cè)一起使用痊远,可以在需要自定義header的場(chǎng)景下使用
  • Access-Control-Allow-Credentials:true 這個(gè)參數(shù)只有當(dāng)需要跨域使用cookie傳遞時(shí)才需要設(shè)置為true垮抗,并且需要前端ajax配置使用xhrField:{withCredential:true}時(shí)才能傳遞cookie,另外safari和最新版本的chrome瀏覽器還需要在設(shè)置內(nèi)放開對(duì)應(yīng)限制碧聪,可參考我的秒殺課程,當(dāng)這個(gè)參數(shù)被設(shè)置成true時(shí)候Access-Control-Allow-Origin就不能設(shè)置為*借宵,否則就變成任何origin域都能允許傳遞cookie了,可將其調(diào)整為前端origin字段傳什么我就用什么

若你使用的是nginx反向代理矾削,則可以直接在nginx反向代理上配置

location /{
    proxy_pass http://backendserver;

    add_header Access-Control-Allow-Methods *;
    add_header Access-Control-Allow-Credentials true;
    add_header Access-Control-Allow-Origin $http_origin;
    add_header Access-Control-Allow-Headers *;
    
}

代理法

打破不同源的限制壤玫,我只要讓它同源就可以了,比如要我的靜態(tài)頁(yè)面是 http://a.com/index.html 動(dòng)態(tài)ajax請(qǐng)求訪問(wèn)的是http://b.com/api/***

我只需要將對(duì)應(yīng)的服務(wù)部署在不同的機(jī)器上哼凯,然后使用一個(gè)公共的c.com的域名作為nginx反向代理的入口域名欲间,在將靜態(tài)服務(wù)和動(dòng)態(tài)服務(wù)分別掛在后面的被代理局域網(wǎng)服務(wù)器內(nèi),修改配置

server{
    listen:80;
    server_name: c.com;

    #靜態(tài)資源
    location /{
        proxy_pass http://localhost:8080/;
    }

    #ajax動(dòng)態(tài)請(qǐng)求
    location /api{
        proxy_pass http://localhost:8081/;

    }

}

這樣就變成同源了

寫在最后

  • 第一:看完點(diǎn)贊断部,感謝您對(duì)作者的認(rèn)可猎贴;
  • ...
  • 第二:隨手轉(zhuǎn)發(fā),分享知識(shí)蝴光,讓更多人學(xué)習(xí)到她渴;
  • ...
  • 第三:記得點(diǎn)關(guān)注,每天更新的C锼睢3煤摹!
  • ...
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疆虚,一起剝皮案震驚了整個(gè)濱河市苛败,隨后出現(xiàn)的幾起案子满葛,更是在濱河造成了極大的恐慌,老刑警劉巖罢屈,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘀韧,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡缠捌,警方通過(guò)查閱死者的電腦和手機(jī)锄贷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)曼月,“玉大人谊却,你說(shuō)我怎么就攤上這事∈伲” “怎么了?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵岳锁,是天一觀的道長(zhǎng)绩衷。 經(jīng)常有香客問(wèn)我,道長(zhǎng)激率,這世上最難降的妖魔是什么咳燕? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮乒躺,結(jié)果婚禮上招盲,老公的妹妹穿的比我還像新娘。我一直安慰自己嘉冒,他們只是感情好曹货,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著讳推,像睡著了一般顶籽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上银觅,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天礼饱,我揣著相機(jī)與錄音,去河邊找鬼究驴。 笑死镊绪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洒忧。 我是一名探鬼主播蝴韭,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼熙侍!你這毒婦竟也來(lái)了万皿?” 一聲冷哼從身側(cè)響起摧找,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎牢硅,沒想到半個(gè)月后蹬耘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡减余,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年综苔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片位岔。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡如筛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抒抬,到底是詐尸還是另有隱情杨刨,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布擦剑,位于F島的核電站妖胀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惠勒。R本人自食惡果不足惜赚抡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纠屋。 院中可真熱鬧涂臣,春花似錦、人聲如沸售担。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)族铆。三九已至吼和,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間骑素,已是汗流浹背炫乓。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留献丑,地道東北人末捣。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像创橄,于是被迫代替她去往敵國(guó)和親箩做。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

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

  • 題目1.什么是同源策略? 同源策略(Same origin Policy): 瀏覽器出于安全方面的考慮妥畏,只允許與本...
    FLYSASA閱讀 1,727評(píng)論 0 6
  • 1. 什么是跨域 跨域邦邦,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本安吁。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScri...
    cbw100閱讀 6,341評(píng)論 2 86
  • 什么是跨域 跨域燃辖,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本鬼店。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript實(shí)...
    他方l閱讀 1,064評(píng)論 0 2
  • 什么是跨域 跨域黔龟,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本妇智。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript實(shí)...
    Yaoxue9閱讀 1,301評(píng)論 0 6
  • 什么是跨域 跨域氏身,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本巍棱。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript實(shí)...
    HeroXin閱讀 837評(píng)論 0 4