Python 使用restful API授权。访问装饰器内的当前_标识
我使用flask restful创建API。我使用了Python 使用restful API授权。访问装饰器内的当前_标识,python,flask,flask-restful,flask-jwt,Python,Flask,Flask Restful,Flask Jwt,我使用flask restful创建API。我使用了jwt来启用基于jwt的身份验证。现在我需要做授权 我试着把我的授权放在装饰器上 test.py(/test-api) 基本上,为了处理基本授权,我需要访问当前\u标识,并检查其类型。然后根据它的类型,我将决定用户是否有权访问api/资源 但是当前\u标识在该装饰器中似乎是空的。因此,为了间接获得它,我必须查看jwt_handler的代码,并在那里做一些事情 授权\u helper.py from functools import wraps
jwt
来启用基于jwt
的身份验证。现在我需要做授权
我试着把我的授权放在装饰器上
test.py(/test-api)
基本上,为了处理基本授权,我需要访问
当前\u标识
,并检查其类型。然后根据它的类型,我将决定用户是否有权访问api/资源
但是
当前\u标识
在该装饰器中似乎是空的
。因此,为了间接获得它,我必须查看jwt_handler
的代码,并在那里做一些事情
授权\u 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
为什么我不能在我的
authorized\u api\u user\u type
decorator中访问current\u identity
?在flask restful中进行授权的正确方法是什么?我当前的解决方案如下所示:
@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
访问decorator中的标识。我从代码中删除了current_identity
。这条路还是很乱 这里是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)
职位
到localhost:5000/auth
并获取access\u令牌作为响应
然后获取带有标题的localhost:5000/
Authorization: JWT `the access_token value above`
你会得到
{
"hello": "user1"
}
如果您尝试使用user2的JWT令牌访问localhost:5000/
,您将得到401
装饰器的包装方式如下:
for decorator in self.decorators:
resource_func = decorator(resource_func)
因此,decorators数组中的后一个可以更早地运行
更多参考:
使用以下方法:
from flask_jwt import current_identity
@jwt_required()
def get(self):
return {'current_identity': current_identity.json()}
你们读过这个问题吗?问题是如何在decorator中访问current\u identity
。current\u identity
如果由jwt\u required
decorator包装,则可以访问。为什么你需要一个定制的装饰器?装饰器可以用于许多情况。例如-检测用户的角色。为了避免在所有视图中重写代码,您可以创建类似“detect_role”的装饰器。请阅读OP的全部问题。好的,我明白你的意思。我会尽快解决这个问题(在我自己的项目中)。我已经阅读了jwt\u required
的源代码,当前的\u标识被注入其中的堆栈中。因此,对于您自己的decorator,我认为如果遵循jwt\u required
@NikolayFominyh,当前的\u标识是可以访问的。我已经用一个自定义的decorator编辑了我的示例,其中包含当前的\u标识。希望它能让您满意,:)在回答线程时,最好避免使用某些短语,如“试试这个”、“使用这个”等。至于2020年,这个解决方案将不起作用。并将产生:TypeError:jwt_required()缺少1个必需的位置参数:“fn”什么是混乱的方式?你的建议是什么?
for decorator in self.decorators:
resource_func = decorator(resource_func)
from flask_jwt import current_identity
@jwt_required()
def get(self):
return {'current_identity': current_identity.json()}