microdot.csrf — proteção CSRF

Rejeita requisições que alteram estado e que se originam de outro site. A verificação é executada como um hook before_request e usa 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 na qual instalar. Opcional; chame initialize() posteriormente se não fornecida.

cors

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

protect_all

Se True (padrão), toda rota exceto GET, HEAD e OPTIONS é protegida automaticamente. Rotas podem ser isentadas individualmente com exempt(). Se False, nenhuma rota é protegida por padrão e rotas individuais aderem com protect().

allow_subdomains

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

initialize(app: Microdot, cors=None)

Anexa-se a app se a construção foi adiada.

exempt(f)

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

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

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

SAFE_METHODS: list

Atributo de classe que lista os métodos que não são protegidos por padrã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}

Uma requisição é permitida quando Sec-Fetch-Site reporta same-origin ou none (ou same-site quando allow_subdomains=True). Se o cabeçalho estiver ausente, o Origin da requisição é comparado com a lista de permissões do CORS. Requisições sem nenhum dos cabeçalhos são aceitas (típico de chamadas de API diretas que não estão sujeitas a CSRF de navegador).