microdot.csrf — CSRF-захист

Відхиляє запити, що змінюють стан і надходять з інших сайтів. Перевірка виконується як хук before_request і використовує заголовок Sec-Fetch-Site, наданий браузером (із заголовком Origin як запасний варіант для старших браузерів, у поєднанні з екземпляром microdot.cors.CORS).

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, що визначає довірені джерела застосунку. Необхідний для резервного переходу до заголовка Origin у браузерах, що не надсилають Sec-Fetch-Site. Необов’язково; без нього застосовується лише перевірка Sec-Fetch-Site.

protect_all

Якщо True (за замовчуванням), кожен маршрут, крім GET, HEAD та OPTIONS, захищається автоматично. Маршрути можна виключити індивідуально через 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)

Декоратор, що примусово вмикає CSRF-захист на маршруті, який інакше був би виключений (наприклад, маршрут GET або будь-який маршрут при protect_all=False).

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-origin або none (або same-site при allow_subdomains=True). Якщо заголовок відсутній, Origin запиту зіставляється зі списком дозволів CORS. Запити без жодного з цих заголовків приймаються (типово для прямих викликів API, що не є об’єктом браузерного CSRF).