iT邦幫忙

3

Week13 - CORS保護了什麼你是否有所誤解?或許你的Server已陷入危險中? - CORS解釋篇 [Server的終局之戰系列]

本文章同時發佈於:


大家好,是否大家在設計前端時,很常遇到跨來源資源共用 - CORS的問題呢?

20200510211658

通常這時候我們會趕快去網路Google一下解決方法,以Express.js為例,我們會安裝cors這個套件,然後快速的貼到後端的code中,這個問題就解決了。

const express = require('express');
const app = express();
const cors = require('cors');

app.use(cors());

app.post('/', function (req, res) {
  res.json({
    hello: 'world'
  });
});

app.listen(3000, function () {
  console.log('App listening on port 3000');
});

但是,你真的清楚自己做了什麼嗎?

到底為什麼會出現CORS,你可能聽說過他是安全機制,但他到底保護了什麼,我們現在的做法會不會有安全疑慮?

什麼是CORS?許多人對他的誤解是?

首先,CORS在是瀏覽器的安全機制

是的這非常重要,這也告訴了我們為什麼我們可以在Postman裡頭呼叫此API卻無法再瀏覽器裡呼叫的原因。

那CORS保護了什麼呢,我以購物平台API Server購物平台網頁惡意購物網頁來舉例:

  1. 小明時常在逛購物平台網頁,所以瀏覽器存有此網站的Cookie。
  2. 有天小明在Google看到惡意購物網頁
  3. 小明發現此網頁跟做得有模有樣,並聲稱自己是購物平台網頁
  4. 小明在網站中看到1折的超優惠產品,就下訂下去了。

此時如果購物平台API Server已將CORS全開,並且CORS的Access-Control-Allow-Credentials也有開啟,惡意購物網頁就可「跨域存取」購物平台網頁的Cookie將請求送至購物平台API Server惡意購物網頁想買什麼就買什麼。

所以CORS不能胡亂全開。

並且,CORS是不是白名單機制

聽了以上例子,有些人可能會認為CORS是白名單機制,事實不然,

CORS實際是防止「瀏覽器端」被惡意誘導,使得在瀏覽器上做出錯誤行為的機制

就如同上面的例子,讓使用者的Cookie被偷取。

因為他是瀏覽器的安全機制,所以我們使用Postman才會可以正常呼叫API,因為跟瀏覽器無關

代理Server是怎麼解決CORS的?

常常聽到有人說透過代理Server可以解決CORS,但問他們說是怎麼用的時候,時常得到「沒有啊就node-http-proxy我照著一些教學貼貼剪剪就好了」,而他實際代表了什麼?

以下解釋CORS沒有開的API Server網頁代理Server的關係:

原本是這樣:

CORS沒有開的API Server -> 網頁

原本我們是這樣,瀏覽器會顯示CORS錯誤。

後來變這樣:

CORS沒有開的API Server -> 代理Server來接收Response,並以開啟CORS的方式往下傳 -> 網頁

由於代理Server「並不是瀏覽器」,所以不會受到CORS沒有開的API Server的CORS影響。


代理Server的應用常見的有兩種:

  1. 前端團隊在開發時,發現後端API為了安全有CORS,所以自架一台簡單的代理Server在自己的電腦上,讓所有的請求都轉發到此代理Server來做處理,避開CORS的問題。
  2. 有些設有CORS的其他方API,後端團隊評估後認為沒有CORS的問題後,透過代理Server來代理請求以避開CORS問題,供前端使用。

簡單的來說就是第1個是前端自己架,為「開發時」使用。第2個是後端架設,「可供開發也可供Release使用」

做個統整

解釋了許多,但其實就只有兩個大重點:

  1. CORS是瀏覽器的安全機制,不是Server的安全機制,但是CORS的啟用/關閉者是Server指使。
  2. CORS是避免「瀏覽器上的不當操作」造成安全性資料「跨域亂傳」,不是白名單機制,這也解釋了為什麼用非瀏覽器如Postman就可以呼叫API的原因。
  3. 承第2點,代理Server即是透過非瀏覽器的角色的關係來收發API請求,就可避開CORS。

參考資料


謝謝你的閱讀,也歡迎分享指教討論~


2 則留言

1
通靈亡
iT邦新手 1 級 ‧ 2020-05-11 15:14:44

觀念和舉例簡潔明瞭!
每個剛踏入前後端的人都會卡關的Cors觀念。

1
Robert Chen
iT邦新手 5 級 ‧ 2020-05-28 23:09:07

API 是如何知道你現在使用的是瀏覽器 or Postman?
用瀏覽器呼叫 API 時有辦法偽裝成 Postman 嗎?

  1. 透過request header的UserAgent
  2. 你可以用UserAgent來偽裝來源,但是request被cors阻擋的部分是瀏覽器,「當API說明他只給Postman這樣的client使用後,瀏覽器會阻擋request」

我要留言

立即登入留言