iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
Modern Web

NestJS 帶你飛!系列 第 28

[NestJS 帶你飛!] DAY28 - CORS

大部分的開發人員在面對前端後端是不同網域的時候,會碰上一個名叫 跨來源資源共享 (Cross-Origin Resource Sharing) 的問題,簡稱 CORS,那這個 CORS 究竟是什麼東西又為什麼會發生呢?這就讓我們來了解一下 CORS 的前因後果吧!

什麼是 CORS?

CORS 是一個控管跨網域請求資源的機制,這個機制可以有效將合法與非合法的跨域存取隔開來,讓合法的跨域存取能夠順利取得資源,而這套機制主要是受到 同源政策 的影響。

同源政策

同源政策的概念很簡單,假設小華有現在很流行的 Switch,他的朋友小明很想玩,所以他可以直接拿來玩不經過小華同意嗎?當然是不行囉,肯定是要經過小華的同意才能夠借來玩,同理,假設 A 網域對 B 網域發出了資源請求,這時候 B 網域同意了 A 網域的存取,那麼這個跨網域的存取才會成功,這就產生出了所謂的 CORS 機制。

CORS 運作模式

CORS 的處理方式會在不同的請求狀況下而有所不同,請求狀況主要分成 簡單請求非簡單請求

簡單請求

簡單請求的條件如下:

  • HTTP Method 為 GETPOSTHEAD 其中一個。
  • Header 僅限:AcceptAccept-LanguageContent-LanguageLast-Event-IDDPRSave-DataViewport-WidthWidth
  • Content-Type 的值僅接受:application/x-www-form-urlencodedmultipart/form-datatext/plain

當該請求為簡單請求時,瀏覽器會判斷其是否為跨域存取並會在 Header 添加相關資訊,若該請求並不屬於合法範圍的話,這個跨域存取將會無效。

非簡單請求

當該請求為非簡單請求時,會先向跨域的伺服器端發送 OPTION 的請求,該伺服器會返回許可規則的 Header,在收到規則後,瀏覽器會判斷這個非簡單請求是否符合許可規則,如果符合就會向跨域的伺服器端發送該請求來存取資源。

Nest 與 CORS

Nest 與 Express 一樣,預設是不允許跨域存取的,若要啟用的話,只需要在 main.ts 中做配置即可,調用 appenableCors(options?: CorsOptions | CorsOptionsDelegate<any>) 這個方法,就可以順利啟用 CORS:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors();
  await app.listen(3000);
}
bootstrap();

Nest 的 CORS 功能其實也是將 Express 的 cors 套件進行打包,並直接內建在 Nest 中,所以 options 的配置與 cors 這個套件的配置項目是相同的。

還有另一種開啟 CORS 的方法,就是直接在 NestFactorycreate 方法中帶入 cors 選項,以下方程式碼為例,直接帶入 true 的效果與 enableCors() 是相同的:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { cors: true });
  await app.listen(3000);
}
bootstrap();

小結

CORS 的問題可以說是非常容易遇到,特別是在前後端分離的情況下。真正上線的時候,通常 不會 允許所有跨域存取都是許可的,都會針對特定網域設置白名單等,所以產品上線的時候千萬要記得配置 options 啊!

參考資料

MDN CORS


上一篇
[NestJS 帶你飛!] DAY27 - Swagger (下)
下一篇
[NestJS 帶你飛!] DAY29 - 實戰演練 (上)
系列文
NestJS 帶你飛!32

1 則留言

0
json_liang
iT邦新手 4 級 ‧ 2021-10-14 17:48:25

這個配置真的很重要!感謝分享

我要留言

立即登入留言