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 додатковими рядками ви вже маєте деяку примітивну форму безпеки.