結(jié)合Nodejs學(xué)習(xí)跨域問(wèn)題

下面我以簡(jiǎn)單的兩臺(tái)node服務(wù)器來(lái)說(shuō)明如何使用nginx進(jìn)行前端跨域訪問(wèn)。

  1. node1服務(wù)器 在localhost:8083上啟動(dòng)
const app = express();
app.get('/web/users',(req, res)=>{
    res.json([{name:"張三",age:12},{name:"李四",age:14}]);
    res.end()
})
app.listen(process.env.PORT || 8083);

同域下的前端代碼只需調(diào)用

function getUsers() {
        var xhr=new XMLHttpRequest();
        xhr.open('GET', 'http://localhost:8083/web/users');
        xhr.send(null);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && xhr.status == 200) {
              alert(xhr.responseText);
            }else {
              alert(xhr.statusText);
            }
        }
}

這里有一點(diǎn)需要關(guān)注的是,前后端代碼處在同一個(gè)域下,xhr.open() url路徑寫(xiě)成下面這樣也是可以的浩螺,它會(huì)默認(rèn)請(qǐng)求到http://localhost:8083/web/users

xhr.open('GET', '/web/users');

下面我們將node1服務(wù)器中的web/users接口刪除:

const app = express();
app.listen(process.env.PORT || 8083);

前端此時(shí)自然無(wú)法訪問(wèn)后臺(tái)的web/users了疹启,將報(bào)一個(gè)404錯(cuò)誤岖免。

下面增加一個(gè)node2服務(wù)器溉浙,在localhost:8085上啟動(dòng)投放,同時(shí)我們將原先在8083上刪除的web/users接口搬遷到8085上:

const app = express();
app.get('/web/users',(req, res)=>{
    res.json([{name:"張三",age:12},{name:"李四",age:14}]);
    res.end()
})
app.listen(process.env.PORT || 8085);

由于8085實(shí)現(xiàn)了這個(gè)接口宏赘,我們嘗試在原先8083端口下的ajax調(diào)用它試試:

 xhr.open('GET', 'http://localhost:8085/web/users');

如我們所料绒北,瀏覽器阻止了此次行為,并拋出一個(gè)跨域錯(cuò)誤察署。


image

難道就無(wú)法訪問(wèn)那個(gè)接口了嗎闷游?其實(shí)服務(wù)器之間和服務(wù)器之間是可以相互調(diào)用的,阻止跨域訪問(wèn)只是在瀏覽器端做的限制而已。

下面我通過(guò)兩種方式來(lái)實(shí)現(xiàn)如何訪問(wèn)到8085上的web/users接口脐往。

1 . node直接作為代理訪問(wèn)

原理就是交由8083后端去訪問(wèn)8085端口接口休吠,訪問(wèn)完成交給前端
8083node后端實(shí)現(xiàn)代碼:

npm install request --save // 需要安裝一個(gè)http request模塊
const app = express()
const request = require('request')
// 訪問(wèn)此接口時(shí)通過(guò)request模塊去訪問(wèn)8085 再返回給前端。
app.get('/web/users',(req, res)=>{
    var url='http://localhost:8085'+req.url
    console.log(url) // http://localhost:8085/web/users
    req.pipe(request(url)).pipe(res);
})

2. jsonp方式訪問(wèn)

就是通過(guò)script 的src业簿,向服務(wù)器請(qǐng)求數(shù)據(jù)瘤礁,且這不受同源策略限制;然后服務(wù)器將相應(yīng)的數(shù)據(jù)放入指定的函數(shù)回調(diào)名中梅尤,返回給前端柜思。說(shuō)的有點(diǎn)繞,下面通過(guò)實(shí)例講解:
8083前端請(qǐng)求8085巷燥,這里已經(jīng)不再是ajax請(qǐng)求了赡盘,而是直接加載8085上資源。

 <script>
       function getUsers(data) {
         alert(data)
       }
    </script>
    <script src="http://localhost:8085/jsonp?callback=getUsers"></script>

上述代碼第一個(gè)script標(biāo)簽定義了一個(gè)函數(shù)getUsers 但是并沒(méi)有執(zhí)行缰揪,只是定義了而已陨享,要想有執(zhí)行能力,需要

getUsers(data) 

所以我們要讓第二個(gè)標(biāo)簽script src="http://localhost:8085/jsonp?callback=getUsers" 返回getUsers(data)內(nèi)容即可钝腺,這樣第一個(gè)標(biāo)簽內(nèi)定義的函數(shù)就可以執(zhí)行了霉咨。返回接口內(nèi)容只需要放到函數(shù)參數(shù)里即可
后臺(tái)8085實(shí)現(xiàn):

const app = express();
const querystring=require('querystring')
const url=require('url')

// 處理前端jsonp請(qǐng)求
app.get('/jsonp',(req,res)=>{
  var qs = querystring.parse(req.url.split('?')[1]); //{callback:'getUsers'}
  var users=JSON.stringify([{name:"張三",age:12},{name:"李四",age:14}]) // 注意需要傳成字符串格式
  var callback=`${qs.callback}(${users})`
  res.end(callback)
})

前端返回


image

是不是有點(diǎn)黑魔法的味道!但是缺點(diǎn)也是明顯的拍屑,首先通過(guò)此方式有一定安全性的途戒,通過(guò)callback后加一些亂七八糟的東西可能會(huì)有xss攻擊,最主要的是jsonp不支持post方法僵驰。

3 .nginx反向代理器

此方式即類似于第一種node代理方式喷斋,也是通過(guò)服務(wù)器和服務(wù)器之間通信,只是不需要8083下后臺(tái)服務(wù)器自己去訪問(wèn)8085蒜茴,而是專門交給nginx,為什么星爪?姑且認(rèn)為nginx更加專業(yè)吧!
nginx配置

server {
        listen 8007;          # nginx啟動(dòng)端口,需要訪問(wèn)這個(gè)端口才能夠代理
        server_name localhost:8083; # 需要代理的服務(wù)器
        location / {          # 如果你訪問(wèn)127.0.0.1/8002/的話nginx去請(qǐng)求
          proxy_pass http://localhost:8083;
        }
        location /web { #訪問(wèn)/web/aa時(shí)會(huì)映射成http://localhost:8085/web/aa;
          proxy_pass   http://localhost:8085;
        }
    }

8083請(qǐng)求路徑

xhr.open('GET', '/web/users');
image

3 CORS

CORS全稱是跨域資源共享 是一個(gè)W3C標(biāo)準(zhǔn)粉私,它規(guī)定瀏覽器允許發(fā)送ajax到不同域下的服務(wù)器來(lái)獲取數(shù)據(jù)顽腾,從而克服了原來(lái)限制,使用CORS需要前后端都支持,現(xiàn)代瀏覽器基本上都支持诺核。具體CORS的知識(shí)可以參考阮一峰博客 http://www.ruanyifeng.com/blog/2016/04/cors.html抄肖。node實(shí)現(xiàn)只需要增加代碼

app.use('*',function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*'); //這個(gè)表示任意域名都可以訪問(wèn),這樣寫(xiě)不能攜帶cookie了窖杀。
//res.header('Access-Control-Allow-Origin', 'http://www.baidu.com'); //這樣寫(xiě)漓摩,只有www.baidu.com 可以訪問(wèn)。
  res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
  res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');//設(shè)置方法
  if (req.method == 'OPTIONS') {
    res.send(200); 
  }
  else {
    next();
  }
});

或者使用現(xiàn)成的CORS模塊

npm install cors
var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
  origin: 'http://www.baidu.com',
  optionsSuccessStatus: 200 
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: '只有百度可以訪問(wèn)'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

如有不正確入客,請(qǐng)指正_

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末管毙,一起剝皮案震驚了整個(gè)濱河市腿椎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌夭咬,老刑警劉巖啃炸,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異卓舵,居然都是意外死亡南用,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門边器,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人托修,你說(shuō)我怎么就攤上這事忘巧。” “怎么了睦刃?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵砚嘴,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我涩拙,道長(zhǎng)际长,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任兴泥,我火速辦了婚禮工育,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘搓彻。我一直安慰自己如绸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布旭贬。 她就那樣靜靜地躺著怔接,像睡著了一般。 火紅的嫁衣襯著肌膚如雪稀轨。 梳的紋絲不亂的頭發(fā)上扼脐,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音奋刽,去河邊找鬼瓦侮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛佣谐,可吹牛的內(nèi)容都是我干的脏榆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼台谍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼须喂!你這毒婦竟也來(lái)了吁断?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤坞生,失蹤者是張志新(化名)和其女友劉穎仔役,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體是己,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡又兵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卒废。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沛厨。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖摔认,靈堂內(nèi)的尸體忽然破棺而出逆皮,到底是詐尸還是另有隱情,我是刑警寧澤参袱,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布电谣,位于F島的核電站,受9級(jí)特大地震影響抹蚀,放射性物質(zhì)發(fā)生泄漏剿牺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一环壤、第九天 我趴在偏房一處隱蔽的房頂上張望晒来。 院中可真熱鬧,春花似錦郑现、人聲如沸潜索。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)竹习。三九已至,卻和暖如春列牺,著一層夾襖步出監(jiān)牢的瞬間整陌,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工瞎领, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留泌辫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓九默,卻偏偏與公主長(zhǎng)得像震放,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驼修,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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

  • 傳統(tǒng)的javaee架構(gòu) 下面是常見(jiàn)的 javaee 架構(gòu)的簡(jiǎn)化版殿遂,客戶端請(qǐng)求 apache/nginx 代理服務(wù)器...
    hxy__閱讀 508評(píng)論 0 2
  • 題目1.什么是同源策略? 同源策略(Same origin Policy): 瀏覽器出于安全方面的考慮诈铛,只允許與本...
    FLYSASA閱讀 1,724評(píng)論 0 6
  • 什么是跨域 跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本墨礁。它是由瀏覽器的同源策略造成的幢竹,是瀏覽器對(duì)JavaScript實(shí)...
    他方l閱讀 1,064評(píng)論 0 2
  • 原文出自:https://www.pandashen.com 同源策略 同源策略/SOP(Same origin ...
    PandaShen閱讀 1,002評(píng)論 0 3
  • 什么是跨域 JavaScript出于安全方面的考慮,不允許跨域調(diào)用其他頁(yè)面的對(duì)象恩静。那什么是跨域呢焕毫,簡(jiǎn)單地理解就是因...
    oWSQo閱讀 404評(píng)論 1 3