基于nodejs koa2的解決跨域中間件設(shè)計(jì)

一囚霸、解決瀏覽器跨域問(wèn)題的方法有很多種

  1. 通過(guò)后端設(shè)置 http Access-Control-* 相關(guān)響應(yīng)頭
  2. 通過(guò) Jsonp
  3. 通過(guò) nginx 反向代理

關(guān)于這三種解決跨域方法的介紹可以看我的另外一篇文章: 如何解決前端跨域問(wèn)題

本文主要講基于 nodejs koa2 實(shí)現(xiàn)第一種跨域方案,并設(shè)計(jì)成 koa2 中間件

二、跨域中間件實(shí)現(xiàn)的功能

  1. 支持跨域 cookie
  2. 支持指定的跨域 http 請(qǐng)求頭拿撩,比如 accesstoken 等
  3. 對(duì)預(yù)檢結(jié)果進(jìn)行緩存,緩存時(shí)間設(shè)置為1天(即86400秒)
  4. 當(dāng)http method 為 OPTIONS時(shí)屯仗,為預(yù)檢時(shí)近刘,此時(shí)直接返回空響應(yīng)體,對(duì)應(yīng)的 http 狀態(tài)碼為 204

三、koa-cors 中間件代碼

koa-cors.js

const URL = require('url');
/**
 * 關(guān)鍵點(diǎn):
 * 1联逻、如果需要支持 cookies,
 *    Access-Control-Allow-Origin 不能設(shè)置為 *,
 *    并且 Access-Control-Allow-Credentials 需要設(shè)置為 true
 *    (注意前端請(qǐng)求需要設(shè)置 withCredentials = true)
 * 2、當(dāng) method = OPTIONS 時(shí), 屬于預(yù)檢(復(fù)雜請(qǐng)求), 當(dāng)為預(yù)檢時(shí), 可以直接返回空響應(yīng)體, 對(duì)應(yīng)的 http 狀態(tài)碼為 204
 * 3检痰、通過(guò) Access-Control-Max-Age 可以設(shè)置預(yù)檢結(jié)果的緩存, 單位(秒)
 * 4包归、通過(guò) Access-Control-Allow-Headers 設(shè)置需要支持的跨域請(qǐng)求頭
 * 5、通過(guò) Access-Control-Allow-Methods 設(shè)置需要支持的跨域請(qǐng)求方法
 */
module.exports = async function (ctx, next) {
  const origin = URL.parse(ctx.get('origin') || ctx.get('referer') || '');
  if (origin.protocol && origin.host) {
    ctx.set('Access-Control-Allow-Origin', `${origin.protocol}//${origin.host}`);
    ctx.set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, DELETE, PUT');
    ctx.set('Access-Control-Allow-Headers', 'X-Requested-With, User-Agent, Referer, Content-Type, Cache-Control,accesstoken');
    ctx.set('Access-Control-Max-Age', '86400');
    ctx.set('Access-Control-Allow-Credentials', 'true');
  }
  if (ctx.method !== 'OPTIONS') {
    // 如果請(qǐng)求類(lèi)型為非預(yù)檢請(qǐng)求铅歼,則進(jìn)入下一個(gè)中間件(包括路由中間件等)
    await next();
  } else {
    // 當(dāng)為預(yù)檢時(shí)公壤,直接返回204,代表空響應(yīng)體
    ctx.body = '';
    ctx.status = 204;
  }
};

Access-Control-Allow-Origin:

Access-Control-Allow-Origin 可以設(shè)置為 * 通配符换可,也可以指定具體的地址比如:https://developer.mozilla.org

當(dāng)把 Access-Control-Allow-Origin 設(shè)置為 * 時(shí)厦幅,表示允許所有資源訪問(wèn)沾鳄,但是此時(shí)不支持帶 credentials 的請(qǐng)求,

因此為了實(shí)現(xiàn)允許所有資源訪問(wèn)且支持帶 credentials 的請(qǐng)求确憨,將其設(shè)置為 ${origin.protocol}//${origin.host}(即動(dòng)態(tài)獲取訪問(wèn)者地址)

Access-Control-Allow-Headers

默認(rèn)支持 Accept译荞、Accept-Language、Content-Language休弃、Content-Type (只支持 application/x-www-form-urlencoded, multipart/form-data, or text/plain)吞歼。

如果請(qǐng)求頭需要添加自定義的 http header 比如 access_token ,那么需要將 access_token 添加進(jìn)數(shù)組中

Access-Control-Allow-Credentials

簡(jiǎn)單的理解就是支持 cookie

Access-Control-Max-Age

設(shè)置 OPTIONS 請(qǐng)求(預(yù)檢請(qǐng)求)的返回結(jié)果的緩存時(shí)間, 單位s

關(guān)于 OPTIONS 請(qǐng)求:
在非簡(jiǎn)單請(qǐng)求且跨域的情況下,瀏覽器會(huì)發(fā)起 options 預(yù)檢請(qǐng)求塔猾。
可以參考我的另一篇文章:關(guān)于瀏覽器預(yù)檢請(qǐng)求

四篙骡、使用方法

app.js

const cors = require('./middlewares/koa-cors');
app.use(cors); // 跨域

五、github 代碼

https://github.com/SimpleCodeCX/myCode/tree/master/nodejs/koa2/cors-demo

參考文檔:

Access-Control-Allow-Headers

credentials

Access-Control-Allow-Credentials

Access-Control-Max-Age

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末桥帆,一起剝皮案震驚了整個(gè)濱河市医增,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌老虫,老刑警劉巖叶骨,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異祈匙,居然都是意外死亡忽刽,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)夺欲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)跪帝,“玉大人,你說(shuō)我怎么就攤上這事些阅∩〗#” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵市埋,是天一觀的道長(zhǎng)黎泣。 經(jīng)常有香客問(wèn)我,道長(zhǎng)缤谎,這世上最難降的妖魔是什么抒倚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮坷澡,結(jié)果婚禮上托呕,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好项郊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布馅扣。 她就那樣靜靜地躺著,像睡著了一般呆抑。 火紅的嫁衣襯著肌膚如雪岂嗓。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天鹊碍,我揣著相機(jī)與錄音厌殉,去河邊找鬼。 笑死侈咕,一個(gè)胖子當(dāng)著我的面吹牛公罕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耀销,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼楼眷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了熊尉?” 一聲冷哼從身側(cè)響起罐柳,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狰住,沒(méi)想到半個(gè)月后张吉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡催植,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年肮蛹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片创南。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡伦忠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出稿辙,到底是詐尸還是另有隱情昆码,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布邻储,位于F島的核電站未桥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏芥备。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一舌菜、第九天 我趴在偏房一處隱蔽的房頂上張望萌壳。 院中可真熱鬧,春花似錦、人聲如沸袱瓮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尺借。三九已至绊起,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間燎斩,已是汗流浹背虱歪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栅表,地道東北人笋鄙。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像怪瓶,于是被迫代替她去往敵國(guó)和親萧落。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

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

  • 1. 什么是跨域 跨域洗贰,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本找岖。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScri...
    cbw100閱讀 6,332評(píng)論 2 86
  • 什么是跨域 跨域敛滋,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本许布。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript實(shí)...
    Yaoxue9閱讀 1,299評(píng)論 0 6
  • 什么是跨域 跨域矛缨,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本爹脾。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript實(shí)...
    HeroXin閱讀 836評(píng)論 0 4
  • 一箕昭、簡(jiǎn)介 CORS需要瀏覽器和服務(wù)器同時(shí)支持灵妨。目前,所有瀏覽器都支持該功能落竹,IE瀏覽器不能低于IE10泌霍。 整個(gè)CO...
    mongofeng閱讀 272評(píng)論 0 0
  • CORS即Cross-Origin Resource Sharing,跨域資源共享 CORS分為兩種 一:簡(jiǎn)單的跨...
    _leopold閱讀 18,860評(píng)論 0 9