跨域原理及其多種解決方式

做前端的童鞋必然都會碰到這么一個問題够坐,跨域。這對于不懂這個概念的開發(fā)者是個很痛苦的事情恤煞,因為你的控制臺會報這么一個錯誤:


image.png

相信大家對于這個報錯都不陌生的趾撵。那么問題來了侄柔,為什么會報這個錯誤呢?這就要涉及到同源策略了占调,具體什么是同源策略我不多做解釋暂题,自己上網(wǎng)查,這里不做贅述究珊。
在這里我只做簡單的概述薪者,怎樣才會造成跨域問題: 調(diào)用接口的時候,當(dāng)你調(diào)用接口的 域名|協(xié)議|端口 和你瀏覽器的 域名|協(xié)議|端口 不一致時苦银,就會造成跨域問題啸胧。簡單來說赶站,在你在調(diào)用接口或者請求資源的時候幔虏,同源策略就相當(dāng)于法律纺念,一旦觸犯,就會有警察去制止你的行為想括。所以陷谱,簡單來說,我們的目標(biāo)就是把我們調(diào)用接口這件事變得合法瑟蜈。
這里我們先從JS的ajax實現(xiàn)開始闡述

<script type="text/javascript">
function loadXMLDoc() {
  var xmlhttp;
  if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp=new XMLHttpRequest();
  }
else {// code for IE6, IE5
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  //readyState==4 表示 請求已完成烟逊,且響應(yīng)已就緒    xmlhttp.status==200 表示服務(wù)器響應(yīng)成功
    if (xmlhttp.readyState==4 && xmlhttp.status==200) {
 // 返回的信息在 xmlhttp.responseText里面存著呢 
      document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }
  // 用xmlhttp對象開啟一個鏈接  true->異步  false->同步
  xmlhttp.open("GET","接口地址",true);
  // 發(fā)送請求
  xmlhttp.send();
}
</script>

上面代碼就用js簡單的完成了一個ajax請求了。我們看到有個對象xmlhttp,它是由XMLHttpRequest這個構(gòu)造函數(shù)創(chuàng)建的铺根。我們的所有有關(guān)的ajax請求以及相應(yīng)等信息都包含在這個對象之中宪躯。
在不觸犯同源策略的情況下,這樣做事沒問題的位迂。但是一旦觸犯的話访雪,又會像最上面的那張圖一樣。這里掂林,我們的第一個目標(biāo)臣缀,就是干掉這個錯誤!
方法一:
我們仔細(xì)看下這個錯誤:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8020' is therefore not allowed access.
大概我們可以看到上面是這么一個意思:請求頭中沒有 'Access-Control-Allow-Origin'的信息泻帮,所以 源'http://127.0.0.1:8020'是不被允許的精置。嘖嘖嘖,感謝控制臺提示到這份上了锣杂,我想大家應(yīng)該明白了脂倦,問題出在了哪里。在后臺沒有設(shè)置對應(yīng)的 'Access-Control-Allow-Origin' 信息元莫,所以請求不被允許狼讨。所以,這個時候需要你的后臺產(chǎn)生對應(yīng)的配置信息柒竞。請看下面:

Access-Control-Allow-Origin: 允許跨域的url(一般是你瀏覽器的域名政供,* 表示所有) 
Access-Control-Allow-Credentials: true (是否允許攜帶cookie,ajax默認(rèn)是不帶cookie信息的朽基,但可配置)
Content-Type: text/html; charset=utf-8 (相應(yīng)內(nèi)容數(shù)據(jù)類型以及編碼類型)

OK布隔,當(dāng)你的后臺配置了對應(yīng)的信息頭以后,你的跨域問題應(yīng)該已經(jīng)得到了解決稼虎。不過對于我們目前的開發(fā)節(jié)奏來說衅檀,大多數(shù)采用的是封裝好的ajax庫去幫助我們更快速的進(jìn)行ajax請求,我們以jQuery的ajax為例

   $.ajax({
//  請求方式 默認(rèn)是get
      type: 'post',
//  地址
      url: 'url',
//  對于get請求霎俩,這個沒必要去設(shè)置哀军,因為最后都是queryString的形式進(jìn)行發(fā)送
      contentType: 'application/json', //  默認(rèn)是 application/x-www-form-urlencoded
      data: { id: '1' },
//  允許攜帶cookie信息-這個需要和后臺協(xié)商沉眶,看是否需要 (可選)
//  注意: 服務(wù)器端 Access-Control-Allow-Credentials = true 時,參數(shù)Access-Control-Allow-Origin 的值不能為 '*' 杉适。
      xhrFields: {
        withCredentials: true
      },
//  假設(shè)是跨域請求
      crossDomain: true,
      dataType: 'json', //默認(rèn)是json
      success: function (res) {
//  res返回的code不為 0 的 時候谎倔,說明你的請求有問題,這里和我們的主題沒太大關(guān)系
        if (res.code === 0) {
          console.log(res)
        } else {
          console.log(res.message)
        }
      },
      error: function (err) {
        console.log('注冊有誤')
      }
   })

這里我們再講下jQ的第二種避免跨域問題的方式-jsonp

      $.ajax({
         type:"get",    //請求方式
         async:true,    //是否異步
         url:"https://d.jd.com/lab/get",
         dataType:"jsonp",
         crossDomain:true,
         success: function(res) {
          console.log('success', res);
         },
         error: function(res) {
          console.log('error', res);
         }
      });

這里我簡單概述下啥事jsonp(摘抄子百度) : JSONP(JSON with Padding)是JSON的一種“使用模式”猿推,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題片习。
它其實是利用了<script>標(biāo)簽沒有跨域限制的漏洞去達(dá)到請求資源的目的,當(dāng)然這是要后臺進(jìn)行配合的蹬叭。這里有一篇不錯的文章可以進(jìn)行參考 : https://www.cnblogs.com/chenweichu/articles/7492460.html


這里其實我們不妨借助工具去實現(xiàn)我們的跨域行為(nginx反向代理)去利用第三方工具幫助我們?nèi)グl(fā)送請求藕咏,你可以理解這個第三方工具相當(dāng)類似于一個后臺服務(wù)應(yīng)用,而后臺服務(wù)之間接口的調(diào)用是不存在跨域問題的秽五。
有過vue-cli項目開發(fā)經(jīng)驗的童鞋應(yīng)該知道vue為我們提供了一個開發(fā)服務(wù)器孽查,這個開發(fā)服務(wù)器就代理發(fā)送了我們的請求,因此避免了跨域的問題坦喘。
文章講到這盲再,希望對你有幫助,有錯誤的話請指正起宽。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洲胖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坯沪,更是在濱河造成了極大的恐慌绿映,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腐晾,死亡現(xiàn)場離奇詭異叉弦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)藻糖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門淹冰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巨柒,你說我怎么就攤上這事樱拴。” “怎么了洋满?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵晶乔,是天一觀的道長。 經(jīng)常有香客問我牺勾,道長正罢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任驻民,我火速辦了婚禮翻具,結(jié)果婚禮上履怯,老公的妹妹穿的比我還像新娘。我一直安慰自己裆泳,他們只是感情好叹洲,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晾虑,像睡著了一般疹味。 火紅的嫁衣襯著肌膚如雪仅叫。 梳的紋絲不亂的頭發(fā)上帜篇,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音诫咱,去河邊找鬼笙隙。 笑死,一個胖子當(dāng)著我的面吹牛坎缭,可吹牛的內(nèi)容都是我干的竟痰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼掏呼,長吁一口氣:“原來是場噩夢啊……” “哼坏快!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起憎夷,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤莽鸿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拾给,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祥得,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年蒋得,在試婚紗的時候發(fā)現(xiàn)自己被綠了级及。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡额衙,死狀恐怖饮焦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情窍侧,我是刑警寧澤县踢,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站疏之,受9級特大地震影響殿雪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锋爪,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一丙曙、第九天 我趴在偏房一處隱蔽的房頂上張望爸业。 院中可真熱鬧,春花似錦亏镰、人聲如沸扯旷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钧忽。三九已至,卻和暖如春逼肯,著一層夾襖步出監(jiān)牢的瞬間耸黑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工篮幢, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留大刊,地道東北人。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓三椿,卻偏偏與公主長得像缺菌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子搜锰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359

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