Blog Cover Image

Inspire you to have New thinking, Walk out your unique Road.

有的時候,你無意間遇到的一些故事,會激發你的靈感,改變你的想法,接下來你會用與之前全然不同的觀念去創造屬於你獨特的故事。

Sign @MinaYu.

[後端] 解決CORS跨域請求的研究筆記(Python FastAPI + Firebase/Firestore)

Posted on

由於最近在將我的命理服務的前端和後端串接,又遇到了CORS跨域問題,但我記得這個問題先前也有遇過,可是完全忘記之前怎麼解決,所以這次特地寫了一篇文章紀錄。

前言 & 什麼是CORS (Cross-origin resource sharing)

我相信許多其他部落客或技術文章會寫得比我更詳細,這邊就簡短描述一下。

在提及CORS之前,先描述同源策略(Same-origin policy),由於資訊安全的關係,為防止網站內的資源請求(例如前端call後端的API取得資訊,或者前端網站的圖像、CSS及一些資源需要使用外部請求時),必須是同源/同個域名/同個domain,為防止駭客或其他有心人士假冒假的域名侵入你的服務。

但隨著科技的發達呢,現在的軟體服務很多會去使用到第三方或者外部的資源請求,所以就會有CORS跨域請求的出現。

  1. 我最現成的例子是Jamstack,我將我的前端網站架在Github,但後端的API我架在Vercel上,當前端使用fetch對後端的API請求時,出現了Access to Reqeust, ... has been blocked by CORS policy

這應該是蠻多技術人員會遇到的問題。

  1. 先前我的前端網站需要存取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的報錯了!

大家試試看吧!