由於最近在將我的命理服務的前端和後端串接,又遇到了CORS跨域問題,但我記得這個問題先前也有遇過,可是完全忘記之前怎麼解決,所以這次特地寫了一篇文章紀錄。
前言 & 什麼是CORS (Cross-origin resource sharing)
我相信許多其他部落客或技術文章會寫得比我更詳細,這邊就簡短描述一下。
在提及CORS之前,先描述同源策略(Same-origin policy),由於資訊安全的關係,為防止網站內的資源請求(例如前端call後端的API取得資訊,或者前端網站的圖像、CSS及一些資源需要使用外部請求時),必須是同源/同個域名/同個domain,為防止駭客或其他有心人士假冒假的域名侵入你的服務。
但隨著科技的發達呢,現在的軟體服務很多會去使用到第三方或者外部的資源請求,所以就會有CORS跨域請求的出現。
- 我最現成的例子是Jamstack,我將我的前端網站架在Github,但後端的API我架在Vercel上,當前端使用fetch對後端的API請求時,出現了
Access to Reqeust, ... has been blocked by CORS policy
。
這應該是蠻多技術人員會遇到的問題。
- 先前我的前端網站需要存取Google Firestore & Firebase資訊時,也遇到了CORS問題。
但本人非常的健忘,所以以至於這次遇到CORS問題時,又花了些時間找解決方法。
許多以前端為本的解決方法嘗試過了沒有成功,後來才想起是要去後端的部分加上CORS,然後將前端的網域加入白名單,使前端請求能被允許傳入後端API中。
我查了很多關於後端的解決方式,但因為每個人的服務都不同,有的服務需要去NGINX 修改設定,但我的是去後端API層加上CORS實作,所以本篇會以兩個我遇到的案例提供解決方法。
案例一: 前端 React.js with 後端 Python Fask API
當React.js實作的前端網站使用fetch 送出HTTPS 請求時,被後端API 擋下產生CORS問題。
因此這邊的解決方式就是,我們在後端的API層實作CORS,並將前端網域加入白名單,以下是實作程式碼:
# Import fastapi的套件
from fastapi import FastAPI
# Import fastapi的cors功能
from fastapi.middleware.cors import CORSMiddleware
# (1) Init 一個 app
app = FastAPI()
# (2) 將你想要allow請求的白名單放這
origins = [
"http://localhost",
"https://example.com"
]
# (3) Init CORS物件,並將設定及白名單加入app中
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# (4) 撰寫你的api route
@app.get("/")
def hello_word():
return {"Hello": "World"}
案例二: React.js 前端 存取 Google Firestore or Firebase
在此案例為React.js前端網頁存取Google的資料庫(Firestore or Firebase),前端網頁的域名被Google擋掉。
而設定需要去Google Cloud的Console去做設定
先前往Google Firebase Console,選取你的專案(此為fancy-chatroom),然後確認有沒有Authentication在左邊的Navbar。
如果沒有的話,需要進入左邊最下面的所有產品,然後創一個新的Authentication
創好後,回到 Authentication -> Settings -> 授權網域 -> 新增網域,加入你希望能夠allow哪些網站的請求,加入完之後就不會有CORS的報錯了!
大家試試看吧!