You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

13 KiB

Безпека - перші кроки

Уявімо, що ваш backend API працює на певному домені.

А frontend - на іншому домені або в іншому шляху того ж домену (або у мобільному застосунку).

І ви хочете, щоб frontend міг автентифікуватися в backend, використовуючи ім'я користувача та пароль.

Ми можемо використати OAuth2, щоб збудувати це з FastAPI.

Але заощадимо вам час на читання всієї довгої специфікації, щоб знайти лише потрібні дрібниці.

Скористаймося інструментами, які надає FastAPI, щоб обробляти безпеку.

Як це виглядає

Спочатку просто запустімо код і подивімося, як він працює, а потім повернемося, щоб розібратися, що відбувається.

Створіть main.py

Скопіюйте приклад у файл main.py:

{* ../../docs_src/security/tutorial001_an_py310.py *}

Запустіть

/// info | Інформація

Пакет python-multipart автоматично встановлюється з FastAPI, коли ви виконуєте команду pip install "fastapi[standard]".

Однак, якщо ви використовуєте команду pip install fastapi, пакет python-multipart за замовчуванням не включено.

Щоб встановити його вручну, переконайтеся, що ви створили віртуальне оточення, активували його, а потім встановили:

$ pip install python-multipart

Це тому, що OAuth2 використовує «form data» для надсилання username та password.

///

Запустіть приклад:

$ fastapi dev

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Перевірте

Перейдіть до інтерактивної документації: http://127.0.0.1:8000/docs.

Ви побачите щось подібне:

/// check | Кнопка Authorize!

У вас уже є нова блискуча кнопка «Authorize».

А ваша операція шляху має маленький замок у правому верхньому куті, на який можна натиснути.

///

Якщо натиснути її, з’явиться маленька форма авторизації, щоб ввести username і password (та інші необов’язкові поля):

/// note | Примітка

Неважливо, що ви введете у форму, поки що це не спрацює. Але ми скоро це доробимо.

///

Звісно, це не frontend для кінцевих користувачів, але це чудовий інструмент для інтерактивної документації всього вашого API.

Ним може користуватися команда frontend (якою можете бути і ви самі).

Ним можуть користуватися сторонні застосунки та системи.

І ним також можете користуватися ви самі, щоб налагоджувати, перевіряти та тестувати той самий застосунок.

Потік паролю

Тепер повернімося трохи назад і розберімося, що це все таке.

password «flow» - це один зі способів («flows»), визначених в OAuth2, для обробки безпеки та автентифікації.

OAuth2 був спроєктований так, щоб backend або API могли бути незалежними від сервера, який автентифікує користувача.

Але в нашому випадку той самий застосунок FastAPI оброблятиме і API, і автентифікацію.

Тож розгляньмо це у спрощеному вигляді:

  • Користувач вводить username і password у frontend і натискає Enter.
  • Frontend (у браузері користувача) надсилає ці username і password на специфічну URL-адресу нашого API (оголошену як tokenUrl="token").
  • API перевіряє ці username і password та повертає «токен» (ми ще нічого з цього не реалізували).
    • «Токен» - це просто строка з деяким вмістом, який ми можемо пізніше використати, щоб перевірити цього користувача.
    • Зазвичай токен налаштований на завершення строку дії через певний час.
      • Тож користувачу доведеться знову увійти пізніше.
      • І якщо токен викрадуть, ризик менший. Це не як постійний ключ, який працюватиме завжди (у більшості випадків).
  • Frontend тимчасово зберігає цей токен десь.
  • Користувач клікає у frontend, щоб перейти до іншого розділу вебзастосунку.
  • Frontend має отримати ще дані з API.
    • Але для того конкретного кінцевого пункту потрібна автентифікація.
    • Тож, щоб автентифікуватися в нашому API, він надсилає заголовок Authorization зі значенням Bearer плюс токен.
    • Якщо токен містить foobar, вміст заголовка Authorization буде: Bearer foobar.

OAuth2PasswordBearer у FastAPI

FastAPI надає кілька інструментів на різних рівнях абстракції, щоб реалізувати ці функції безпеки.

У цьому прикладі ми використаємо OAuth2 з потоком Password, використовуючи токен Bearer. Це робиться за допомогою класу OAuth2PasswordBearer.

/// info | Інформація

«Bearer»-токен - не єдиний варіант.

Але це найкращий для нашого сценарію.

І, можливо, найкращий для більшості сценаріїв, якщо ви не експерт з OAuth2 і точно не знаєте, чому інша опція краще відповідає вашим потребам.

У такому разі FastAPI теж надає інструменти, щоб це збудувати.

///

Коли ми створюємо екземпляр класу OAuth2PasswordBearer, ми передаємо параметр tokenUrl. Цей параметр містить URL, який клієнт (frontend у браузері користувача) використовуватиме, щоб надіслати username і password для отримання токена.

{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *}

/// tip | Порада

Тут tokenUrl="token" відноситься до відносної URL-адреси token, яку ми ще не створили. Оскільки це відносна URL-адреса, вона еквівалентна ./token.

Тому, якщо ваш API розміщений на https://example.com/, це буде https://example.com/token. А якщо на https://example.com/api/v1/, тоді це буде https://example.com/api/v1/token.

Використання відносної URL-адреси важливе, щоб ваша програма продовжувала працювати навіть у просунутому сценарії, як-от За представником.

///

Цей параметр не створює той endpoint / операцію шляху, а декларує, що URL /token буде тим, який клієнт має використовувати, щоб отримати токен. Ця інформація використовується в OpenAPI, а потім - у системах інтерактивної документації API.

Незабаром ми також створимо фактичну операцію шляху.

/// info | Інформація

Якщо ви дуже строгий «Pythonista», вам може не подобатися стиль імені параметра tokenUrl замість token_url.

Це тому, що використано ту саму назву, що і в специфікації OpenAPI. Тож якщо вам потрібно буде дослідити ці схеми безпеки глибше, ви зможете просто скопіювати та вставити її, щоб знайти більше інформації.

///

Змінна oauth2_scheme - це екземпляр OAuth2PasswordBearer, але це також і «викликаємий» об’єкт.

Його можна викликати так:

oauth2_scheme(some, parameters)

Тож його можна використовувати з Depends.

Використання

Тепер ви можете передати oauth2_scheme як залежність через Depends.

{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}

Ця залежність надасть str, який буде присвоєний параметру token функції операції шляху.

FastAPI знатиме, що може використати цю залежність, щоб визначити «схему безпеки» в схемі OpenAPI (і в автоматичній документації API).

/// info | Технічні деталі

FastAPI знатиме, що може використати клас OAuth2PasswordBearer (оголошений у залежності), щоб визначити схему безпеки в OpenAPI, тому що він наслідує fastapi.security.oauth2.OAuth2, який своєю чергою наслідує fastapi.security.base.SecurityBase.

Усі утиліти безпеки, які інтегруються з OpenAPI (і автоматичною документацією API), наслідують SecurityBase. Так FastAPI розуміє, як інтегрувати їх в OpenAPI.

///

Що відбувається

Вона шукатиме в запиті заголовок Authorization, перевірить, чи його значення - це Bearer плюс деякий токен, і поверне токен як str.

Якщо заголовка Authorization немає або значення не містить токена Bearer , вона одразу відповість помилкою зі статус-кодом 401 (UNAUTHORIZED).

Вам навіть не потрібно перевіряти, чи існує токен, щоб повернути помилку. Ви можете бути певні: якщо ваша функція виконується, у параметрі токена буде str.

Ви вже можете спробувати це в інтерактивній документації:

Ми ще не перевіряємо дійсність токена, але це вже початок.

Підсумок

Отже, лише 3-4 додатковими рядками ви вже маєте деяку примітивну форму безпеки.