microdot.csrf — proteção CSRF

Rejeita pedidos que alterem o estado e que tenham origem em outros sites. A verificação é executada como um hook before_request e utiliza o cabeçalho Sec-Fetch-Site fornecido pelo navegador (com o cabeçalho Origin como alternativa para navegadores mais antigos, quando combinado com uma instância de microdot.cors.CORS).

class CSRF

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

A instância de microdot.Microdot a instalar. Opcional; chame initialize() mais tarde se não for fornecida.

cors

A instância de microdot.cors.CORS que define as origens de confiança da aplicação. Necessária para recorrer ao cabeçalho Origin em navegadores que não enviam Sec-Fetch-Site. Opcional; sem ela, aplica-se apenas a verificação de Sec-Fetch-Site.

protect_all

Se True (predefinição), todas as rotas exceto GET, HEAD e OPTIONS são protegidas automaticamente. As rotas podem ser excluídas individualmente com exempt(). Se False, nenhuma rota é protegida por predefinição e as rotas individuais ativam a proteção com protect().

allow_subdomains

Se True, são aceites pedidos de subdomínios das origens da aplicação (same-site em Sec-Fetch-Site, ou sufixo de origem correspondente).

initialize(app: Microdot, cors=None)

Associa-se a app se a construção foi diferida.

exempt(f)

Decorador que isenta uma rota da proteção CSRF. Coloque-o imediatamente após o decorador da rota:

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

Decorador que força a proteção CSRF numa rota que de outra forma estaria isenta (por exemplo, uma rota GET ou qualquer rota quando protect_all=False).

SAFE_METHODS: list

Atributo de classe com a lista de métodos não protegidos por predefinição — ['GET', 'HEAD', 'OPTIONS'].

Exemplo:

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}

Um pedido é permitido quando Sec-Fetch-Site indica same-origin ou none (ou same-site quando allow_subdomains=True). Se o cabeçalho estiver ausente, o Origin do pedido é verificado contra a lista de permissões do CORS. Os pedidos sem nenhum dos cabeçalhos são aceites (típico em chamadas diretas à API que não estão sujeitas a CSRF do navegador).