microdot.csrf --- CSRF 防護

拒絕來自跨站的狀態變更請求。檢查會以 before_request 掛勾的形式執行,並使用瀏覽器提供的 Sec-Fetch-Site 標頭(在搭配 microdot.cors.CORS 實例時,以 Origin 標頭作為較舊瀏覽器的後備機制)。

class CSRF

class microdot.csrf.CSRF(app: Microdot | None = None, cors=None, protect_all: bool = True, allow_subdomains: bool = False)
app

要安裝的 microdot.Microdot 實例。可選;若未提供則稍後呼叫 initialize()

cors

定義應用程式受信任來源的 microdot.cors.CORS 實例。在不傳送 Sec-Fetch-Site 的瀏覽器上後備使用 Origin 標頭時需要此項。可選;若無此項,則僅套用 Sec-Fetch-Site 檢查。

protect_all

若為 True(預設),則除 GETHEADOPTIONS 之外的每個路由皆自動受到保護。可使用 exempt() 個別豁免路由。若為 False,則預設不保護任何路由,而是由個別路由透過 protect() 選擇加入。

allow_subdomains

若為 True,則接受來自應用程式來源之子網域的請求(same-site 的 Sec-Fetch-Site,或相符的來源後綴)。

initialize(app: Microdot, cors=None)

若建構時延後附加,則附加至 app

exempt(f)

豁免路由免於 CSRF 防護的裝飾器。請將其直接置於路由裝飾器之後::

@app.post('/webhook')
@csrf.exempt
async def webhook(request):
    # accepts cross-site POSTs
protect(f)

強制對原本會被豁免的路由(例如 GET 路由,或當 protect_all=False 時的每個路由)施加 CSRF 防護的裝飾器。

SAFE_METHODS: list

列出預設不受保護之方法的類別屬性 —— ['GET', 'HEAD', 'OPTIONS']

範例::

from microdot import Microdot
from microdot.cors import CORS
from microdot.csrf import CSRF

app = Microdot()
cors = CORS(app, allowed_origins=['https://app.example.com'])
csrf = CSRF(app, cors=cors)

@app.post('/api/save')
async def save(request):
    # automatically CSRF-protected
    return {'ok': True}

Sec-Fetch-Site 回報 same-originnone(或在 allow_subdomains=True 時回報 same-site)時,請求會被允許。若標頭不存在,則會將請求的 Origin 與 CORS 允許清單進行比對。兩種標頭皆無的請求會被接受(這是不受瀏覽器 CSRF 影響的直接 API 呼叫之典型情況)。