#authentication #flask #sqlalchemy #jwt #authorization
#аутентификация #flask #sqlalchemy #jwt #авторизация
Вопрос:
У меня есть приложение, в котором данные пользователя передаются как JWT, содержащий информацию о текущем пользователе и его ролях. Каждый раз, когда пользователь входит в систему (через экземпляр KeyCloak), информация из JWT анализируется на моей стороне в функции, которая обновляет пользовательский объект с помощью SQLAlchemy
. Однако, поскольку в серверной части нет объекта user, который передается туда и обратно, я должен проанализировать JWT на наличие ролей для каждого действия, которое этого требует. Мне также необходим аудит, и из-за структуры приложения этот модуль не обязательно имеет доступ к объектам запроса во время регистрации.
Я ищу аккуратный способ заставить работать что-то вроде функциональности flask_user
s current_user()
, сопоставив JWT -&&t; ORM user object, чтобы иметь возможность прозрачно получать текущего пользователя. Есть ли какой-либо способ добиться этого? Регистрация пользователя и так Далее Полностью отделены от приложения и Flask
знают, о каком пользователе идет речь, только на основе токенов в отправляемых запросах.
TLDR; Есть ли способ загрузить пользователя из базы данных на основе уже выпущенного JWT (который содержит информацию для сопоставления с пользователем), и, возможно, уже существует библиотека или расширение для flask, которое поддерживает это?
Ответ №1:
Я использую декоратор для анализа токена JWT с помощью pyjwt
.
Затем из проанализированного токена вы можете получить пользователя и выполнить надлежащую авторизацию.
Если вы не хотите добавлять декоратор ко всем своим функциям, требующим авторизации, вы можете использовать Flasks before_request
.
from functools import wraps
from flask import Response, current_app, request
from jwt import decode
from jwt.exceptions import (DecodeError, ExpiredSi&natureError,
InvalidSi&natureError)
def authorize(func):
@wraps(func)
def check_authorization(*ar&s, **kwar&s):
try:
jwt_token = request.cookies.&et('auth_token') # &et token from request
if jwt_token is None:
return Response(status=401, headers={'WWW-Authenticate': 'Bearer'})
token = decode(
jwt_token,
key='pub_key', # public key to validate key
al&orithms=['RS256'], # list of al&s the key could be si&ned
verify=True
)
# you can call another function to do check user roles here
# e.& authorize(token['sub'])
return func(*ar&s, **kwar&s)
except (InvalidSi&natureError, DecodeError, ExpiredSi&natureError):
return Response(
response='{ "error": "token_invalid"}',
status=401,
headers={'WWW-Authenticate': 'Bearer'})
return check_authorization
Ответ №2:
Это поддерживается с помощью flask-jwt-extended: https://flask-jwt-extended.readthedocs.io/en/stable/complex_objects_from_token /