欸,各位,先別急著點開 YouTube,看這篇文章,因為今天我要跟你聊聊 FastAPI 的安全跟中介層。別以為這很枯燥,我保證這過程會像在跟自己碎碎念一樣——嗯,就是那種邊敲鍵盤邊偷笑的感覺。
先說前言,我覺得現代 Web 開發就像在蓋城堡,你以為城牆夠高就安全?不,城門口那隻守衛狗可沒那麼簡單,它還得認得來訪的客人是誰。FastAPI 呢?它就是那隻狗的教練,教你怎麼讓城堡安全,但也要你懂得手把手去調整牠的技能,不然狗也可能咬錯人。想像一下,如果你的 API 是城堡,而你的使用者是各路英雄好漢,沒有 CORS、Trusted Host、Rate Limiting,那就等於城門大開,連小偷都能悠哉散步。
在現代 Web 開發中,安全性、流量控制與可信來源管理是不可或缺的核心設計。FastAPI 作為一個高性能的 Python Web 框架,本身提供極佳的擴充性與中介層(Middleware)支持,使開發者可以輕鬆整合安全防護、跨域控制與流量限制。本文將從概念到實務,逐步分析如何在 FastAPI 中實作 CORS、Trusted Host 與 Rate Limiting,並介紹其底層原理與最佳實踐。放心,我保證不會枯燥,因為我們會用比喻、幽默、自嘲,甚至偶爾來點黑色幽默,讓你邊學邊笑。
我得先承認,我第一次碰 CORS (Cross-Origin Resource Sharing) 的時候,差點把鍵盤丟出窗外。為什麼?因為瀏覽器老是對我說:「欸,你這個請求,不是同一個來源,拜託先走後門。」我想說,兄弟,我只是想抓個 JSON 而已,哪裡踩到你的地雷了?
所以,CORS 就是那扇門的守衛,你要明確告訴他:「喂,我認得這幾個朋友,其他人滾蛋。」。FastAPI 提供了 CORSMiddleware 來幫你處理這件事:
CORS 是一種瀏覽器安全機制,用於控制瀏覽器從一個來源(Origin)請求另一個來源的資源。傳統上,瀏覽器的同源策略(Same-Origin Policy, SOP)禁止 JavaScript 從不同的 domain、protocol 或 port 請求資源,以防止跨站腳本攻擊(XSS)與敏感資訊泄露。CORS 提供了一種標準化的方式,允許伺服器明確告訴瀏覽器,哪些來源可以訪問資源。
def setup_middlewares(app: FastAPI):
origins = [
"http://localhost",
"http://localhost:5173",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins, # 指定可信來源
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
簡單來說:
allow_origins
是你的 VIP 名單。別傻傻用 *
,那就像開著城門,還掛著「歡迎小偷光臨」的招牌——你懂的。allow_credentials=True
,允許帶 Cookie 或 Authorization header 進來,但小心被竊取,就像給客人鑰匙之前先確認身份。allow_methods
和 allow_headers
可以指定哪些 HTTP 方法與標頭允許,萬用 *
很方便,但安全性會打折。實務建議:
說到底,CORS 就像你家貓咪對陌生人的警戒心,管得嚴一點,才能安心睡午覺。
再來,聊 Trusted Host。我第一次看到這個概念時,心裡有點:這也太嚴格了吧?但想想,Host Header 攻擊可不只是理論,它真的能讓人篡改 URL,甚至偷走內部資源,簡直比把章魚偷偷放進冰箱還恐怖。
allowed_hosts
支援正則或完整域名列表,指定誰是合法訪客。想像一下,這就像派守衛站在城門口,拿著放大鏡認人。有人假裝是你的朋友想溜進來?Sorry,拒絕入場。
app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=["localhost", "127.0.0.1", "apiGateway"],
)
allowed_hosts
支援正則表達式或完整域名列表。
內網與外網分開管理:
這樣就只認識你指定的客人,其他人一律拒絕進入。內網、外網分開管理,外網要 HTTPS,搭配反向代理,像 Nginx 或 Traefik,那就更安全了。
好了,我知道你可能開始打哈欠,但 Rate Limiting 是我的最愛。這個就像給 API 裝了一個「耐心值」,超過了,哼,就不理你了。
Rate Limiting 的主要用途:
常見策略:
用 Python 的 SlowAPI 套件很方便:
SlowAPI 是一個基於 Flask-Limiter 的 Python 套件,支援 FastAPI,簡化速率限制設定。
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
然後在路由上加限制:
@router.post("/api/v1/ask")
@limiter.limit("7/minute") # 每分鐘 7 次
def ask_question(
request: Request,
user_query: UserQuery,
user_id: str = Depends(verify_firebase_token),
# 這裡處理使用者問題
return {"answer": "Hello, this is your answer!"}
):
當有人狂打你的api 就會變成以下
每分鐘七次,七次啊!有人問我為什麼不多一點,我說:「兄弟,人生也是有限耐心值,不然 API 也會精神崩潰。」
超過了,你就會看到 HTTP 429,像城門貼的「太多客人,請稍候再來」,搞得你忍不住笑又無奈。
因為
from slowapi import _rate_limit_exceeded_handler
def setup_middlewares(app: FastAPI):
limiter = Limiter(key_func=get_remote_address)
app.add_exception_handler(429, _rate_limit_exceeded_handler)
就這樣,API 有了耐心值,再也不怕有人瘋狂刷請求,把後端拖垮。
中介層不是單純的技術,而是一種哲學:給 API 加點自律,也給開發者安全感。
三者組合,就是三個夥伴守著你的城堡:一個看門、一個認人、一個管人潮。
沒有它們,你的 FastAPI 就像無人管理的自助餐廳:人人隨便吃,最後蛋糕被踩爛。安全設計雖然麻煩,但缺了它,你會更麻煩。