iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0
AI & Data

論文流浪記:我與AI 探索工具、組合流程、挑戰完整平台系列 第 21

Day 20|FastAPI 安全大公開!沒 CORS、Trusted Host、Rate Limiting,你的 API 就像無人看管的自助餐廳

  • 分享至 

  • xImage
  •  

前言

欸,各位,先別急著點開 YouTube,看這篇文章,因為今天我要跟你聊聊 FastAPI 的安全跟中介層。別以為這很枯燥,我保證這過程會像在跟自己碎碎念一樣——嗯,就是那種邊敲鍵盤邊偷笑的感覺。

先說前言,我覺得現代 Web 開發就像在蓋城堡,你以為城牆夠高就安全?不,城門口那隻守衛狗可沒那麼簡單,它還得認得來訪的客人是誰。FastAPI 呢?它就是那隻狗的教練,教你怎麼讓城堡安全,但也要你懂得手把手去調整牠的技能,不然狗也可能咬錯人。想像一下,如果你的 API 是城堡,而你的使用者是各路英雄好漢,沒有 CORS、Trusted Host、Rate Limiting,那就等於城門大開,連小偷都能悠哉散步。

在現代 Web 開發中,安全性、流量控制與可信來源管理是不可或缺的核心設計。FastAPI 作為一個高性能的 Python Web 框架,本身提供極佳的擴充性與中介層(Middleware)支持,使開發者可以輕鬆整合安全防護、跨域控制與流量限制。本文將從概念到實務,逐步分析如何在 FastAPI 中實作 CORS、Trusted Host 與 Rate Limiting,並介紹其底層原理與最佳實踐。放心,我保證不會枯燥,因為我們會用比喻、幽默、自嘲,甚至偶爾來點黑色幽默,讓你邊學邊笑。


CORS | 瀏覽器的「不信任感」

我得先承認,我第一次碰 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_methodsallow_headers 可以指定哪些 HTTP 方法與標頭允許,萬用 * 很方便,但安全性會打折。

實務建議:

  • 內網、外網分開規則。內網可以比較寬鬆,外網要嚴格控制來源。
  • HTTPS 必備,不然 CORS 的保護就像城門沒鎖,隔壁小偷隨便就溜進來。
  • 搭配反向代理(Nginx/Traefik)效果更好,這就像把守衛安排在最有效的位置。

說到底,CORS 就像你家貓咪對陌生人的警戒心,管得嚴一點,才能安心睡午覺。


Trusted Host | 認得你的客人

再來,聊 Trusted Host。我第一次看到這個概念時,心裡有點:這也太嚴格了吧?但想想,Host Header 攻擊可不只是理論,它真的能讓人篡改 URL,甚至偷走內部資源,簡直比把章魚偷偷放進冰箱還恐怖。

  • allowed_hosts 支援正則或完整域名列表,指定誰是合法訪客。
  • 內網允許 localhost、127.0.0.1,外網允許你信任的域名。
  • 配合 HTTPS 與反向代理,Host 才不會被冒名頂替。

想像一下,這就像派守衛站在城門口,拿著放大鏡認人。有人假裝是你的朋友想溜進來?Sorry,拒絕入場。


app.add_middleware(
    TrustedHostMiddleware,
    allowed_hosts=["localhost", "127.0.0.1", "apiGateway"],
)
  • allowed_hosts 支援正則表達式或完整域名列表。

  • 內網與外網分開管理:

    • 內網 API:允許 localhost, 127.0.0.1。
    • 外網 API:允許 example.com 或其子域名。

這樣就只認識你指定的客人,其他人一律拒絕進入。內網、外網分開管理,外網要 HTTPS,搭配反向代理,像 Nginx 或 Traefik,那就更安全了。


Rate Limiting | API 的「耐心值」

好了,我知道你可能開始打哈欠,但 Rate Limiting 是我的最愛。這個就像給 API 裝了一個「耐心值」,超過了,哼,就不理你了。

Rate Limiting 的主要用途:

  • 防止 DDoS 攻擊或暴力破解。
  • 避免 API 過量請求導致後端掛掉。
  • 避免少數人濫用資源,公平起見。

常見策略:

  • 固定窗口計數(Fixed Window):時間窗口內限制請求數。
  • 滑動窗口(Sliding Window):較平滑,避免峰值爆炸。
  • 漏桶 / 令牌桶:允許短期突發,長期穩定。

用 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,像城門貼的「太多客人,請稍候再來」,搞得你忍不住笑又無奈。

https://ithelp.ithome.com.tw/upload/images/20250923/20136781pMs4XFSQAb.png

因為

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 加點自律,也給開發者安全感。

  • CORS:警覺心,別人誰能進門。
  • Trusted Host:辨識力,這人是不是真朋友。
  • Rate Limiting:耐心值,別人不能無限消耗你。

三者組合,就是三個夥伴守著你的城堡:一個看門、一個認人、一個管人潮。

沒有它們,你的 FastAPI 就像無人管理的自助餐廳:人人隨便吃,最後蛋糕被踩爛。安全設計雖然麻煩,但缺了它,你會更麻煩。


上一篇
Day 19|每日知識快遞 (下)|再也不用怕 Token 爆掉!工程師的分階段榨乾 LLM 心法
下一篇
Day 21|Makefile 活到 2025!懶人工程師的 AI 專案「萬能遙控器」
系列文
論文流浪記:我與AI 探索工具、組合流程、挑戰完整平台23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言