Flask-restful API Авторизация. Доступ к current_identity внутри декоратора
Я использую колбу для создания своих API. я использовал flask-jwt
для включения аутентификации на основе JWT
, Теперь мне нужно сделать авторизацию.
Я попытался поставить авторизацию декоратора.
test.py (/ test api)
from flask_restful import Resource
from flask_jwt import jwt_required
from authorization_helper import authorized_api_user_type
class Test(Resource):
decorators = [jwt_required(), authorized_api_user_type()]
def get(self):
return 'GET OK'
def post(self):
return 'POST OK'
В основном, чтобы справиться с основной авторизацией, мне нужен доступ current_identity
и проверьте его тип. Затем, основываясь на его типе, я решу, авторизован ли пользователь для доступа к API / ресурсам.
Но current_identity
по-видимому empty
в этом декораторе. Таким образом, чтобы получить его косвенно, я должен был увидеть код jwt_handler
и делать то, что сделано там.
authorization_helper.py
from functools import wraps
from flask_jwt import _jwt, JWTError
import jwt
from models import Teacher, Student
def authorized_api_user_type(realm=None, user_type='teacher'):
def wrapper(fn):
@wraps(fn)
def decorator(*args, **kwargs):
token = _jwt.request_callback()
if token is None:
raise JWTError('Authorization Required', 'Request does not contain an access token',
headers={'WWW-Authenticate': 'JWT realm="%s"' % realm})
try:
payload = _jwt.jwt_decode_callback(token)
except jwt.InvalidTokenError as e:
raise JWTError('Invalid token', str(e))
identity = _jwt.identity_callback(payload)
if user_type == 'student' and isinstance(identity, Student):
return fn(*args, **kwargs)
elif user_type == 'teacher' and isinstance(identity, Teacher):
return fn(*args, **kwargs)
# NOTE - By default JWTError throws 401. We needed 404. Hence status_code=404
raise JWTError('Unauthorized',
'You are unauthorized to request the api or access the resource',
status_code=404)
return decorator
return wrapper
Почему я не могу просто получить доступ current_identity
в моем authorized_api_user_type
декоратор? Какой ПРАВИЛЬНЫЙ способ сделать авторизацию в флеш-отдыхе?
3 ответа
Вот сочетание быстрых стартов обоих Flask-JWT
а также Flask-Restful
,
from flask import Flask
from flask_restful import Resource, Api, abort
from functools import wraps
app = Flask(__name__)
api = Api(app)
from flask_jwt import JWT, jwt_required, current_identity
from werkzeug.security import safe_str_cmp
class User(object):
def __init__(self, id, username, password):
self.id = id
self.username = username
self.password = password
def __str__(self):
return "User(id='%s')" % self.id
users = [
User(1, 'user1', 'abcxyz'),
User(2, 'user2', 'abcxyz'),
]
username_table = {u.username: u for u in users}
userid_table = {u.id: u for u in users}
def authenticate(username, password):
user = username_table.get(username, None)
if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')):
return user
def identity(payload):
user_id = payload['identity']
return userid_table.get(user_id, None)
app.config['SECRET_KEY'] = 'super-secret'
jwt = JWT(app, authenticate, identity)
def checkuser(func):
@wraps(func)
def wrapper(*args, **kwargs):
if current_identity.username == 'user1':
return func(*args, **kwargs)
return abort(401)
return wrapper
class HelloWorld(Resource):
decorators = [checkuser, jwt_required()]
def get(self):
return {'hello': current_identity.username}
api.add_resource(HelloWorld, '/')
if __name__ == '__main__':
app.run(debug=True)
СООБЩЕНИЕ
{
"username": "user1",
"password": "abcxyz"
}
к localhost:5000/auth
и получить access_token
в ответ.
Тогда ПОЛУЧИТЕ localhost:5000/
с заголовком
Authorization: JWT `the access_token value above`
Вы бы получили
{
"hello": "user1"
}
если вы попытаетесь получить доступ localhost:5000/
с токеном JWT user2, вы получите 401
,
Декораторы оборачиваются следующим образом:
for decorator in self.decorators:
resource_func = decorator(resource_func)
https://github.com/flask-restful/flask-restful/blob/master/flask_restful/__init__.py
Таким образом, последний в массиве decorators запускается раньше.
Для получения дополнительной информации:
https://github.com/rchampa/timetable/blob/master/restful/users.py
Мое текущее решение выглядит так:
@app.before_request
def detect_something():
header = request.headers.get('Authorization')
if header:
_, token = header.split()
request.identity = identity(jwt.decode(token,
app.config['SECRET_KEY']))
После этого мы можем получить доступ к личности в декораторе через request.identity
, И я удалила current_identity
везде из кода. Это все еще грязный путь.
Использовать этот:
from flask_jwt import current_identity
@jwt_required()
def get(self):
return {'current_identity': current_identity.json()}