restful español python flask flask-restful flask-jwt

python - español - flask>-< restful



Autorización de la API de Frask-restful. Accede a current_identity dentro del decorador. (3)

Aquí está la combinación de Flask-Restful de Flask-JWT y 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)

ENVIAR

{ "username": "user1", "password": "abcxyz" }

Para localhost:5000/auth y obtener el access_token en respuesta.

Entonces GET localhost:5000/ con encabezado

Authorization: JWT `the access_token value above`

Obtendrías

{ "hello": "user1" }

si intenta acceder a localhost:5000/ con el token JWT de user2, obtendría 401 .

Los decoradores se envuelven de esta manera:

for decorator in self.decorators: resource_func = decorator(resource_func)

https://github.com/flask-restful/flask-restful/blob/master/flask_restful/init.py#L445

Así que el último en la serie de decoradores se ejecuta antes.

Para más referencia:

https://github.com/rchampa/timetable/blob/master/restful/users.py

https://github.com/mattupstate/flask-jwt/issues/37

Utilizo matraz-restful para crear mis APIs. He utilizado flask-jwt para habilitar la autenticación basada en JWT . Ahora necesito hacer la autorización.

He intentado poner mi decorador de autorizaciones.

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''

Básicamente para manejar la autorización básica, necesito acceder a current_identity y verificar su tipo. Luego, en función de su tipo, voy a decidir si el usuario está autorizado para acceder a la api / resources.

Pero current_identity parece estar empty en ese decorador. Así que para adquirirlo indirectamente, tuve que ver el código de jwt_handler y hacer lo que se hace allí.

autorizacion_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

¿Por qué no puedo acceder a current_identity en authorized_api_user_type decorator? ¿Cuál es la forma CORRECTA de hacer la autorización en un matraz reparador?


Mi solución actual se ve como:

@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'']))

Después de esto podemos acceder a la identidad en el decorador a través de la request.identity . Identidad. Y quité current_identity todas partes del código. Todavía es un camino desordenado.


Utilizar esta:

from flask_jwt import current_identity @jwt_required() def get(self): return {''current_identity'': current_identity.json()}