我正在构建基于Flask的REST API并使用Flask-JWT来处理JWT身份验证。我还想使用Flask-Security的内置角色管理。但是,Flask-Security的@roles_required()装饰器假设我在失败时显示Flask视图。
这是我的令牌端点(它正在按我的意愿工作):
$ http POST localhost:5000/auth/token username='test' password='test'
HTTP/1.0 200 OK
Content-Length: 192
Content-Type: application/json
Date: Sun, 08 Nov 2015 17:45:46 GMT
Server: Werkzeug/0.10.4 Python/3.5.0
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NDcwMDQ3NDYsIm5iZiI6MTQ0NzAwNDc0NiwiZXhwIjoxNDQ3MDA1MDQ2LCJpZGVudGl0eSI6MX0.RFIeaLuvJNM9fDjFYFQ7sh_WaDVU-_aM7e46tVJzlBQ"
}
以下是对没有任何角色要求的资源的成功响应(仅使用@jwt_required)这也是我想要的:
$http GET localhost:5000/protected Authorization:'JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NDcwMDQ3NDYsIm5iZiI6MTQ0NzAwNDc0NiwiZXhwIjoxNDQ3MDA1MDQ2LCJpZGVudGl0eSI6MX0.RFIeaLuvJNM9fDjFYFQ7sh_WaDVU-_aM7e46tVJzlBQ'
HTTP/1.0 200 OK
Content-Length: 25
Content-Type: text/html; charset=utf-8
Date: Sun, 08 Nov 2015 17:46:24 GMT
Server: Werkzeug/0.10.4 Python/3.5.0
<models.User[email=test]>
当我对具有所需角色的资源(例如本例中的admin)执行相同操作时,似乎假设我有一个要显示的页面,例如/ login,我没有,因为它是无头REST API:
$ http GET localhost:5000/admin Authorization:'JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NDcwMDQ3NDYsIm5iZiI6MTQ0NzAwNDc0NiwiZXhwIjoxNDQ3MDA1MDQ2LCJpZGVudGl0eSI6MX0.RFIeaLuvJNM9fDjFYFQ7sh_WaDVU-_aM7e46tVJzlBQ'
HTTP/1.0 302 FOUND
Content-Length: 209
Content-Type: text/html; charset=utf-8
Date: Sun, 08 Nov 2015 17:46:43 GMT
Location: http://localhost:5000/
Server: Werkzeug/0.10.4 Python/3.5.0
Set-Cookie: session=eyJfZmxhc2hlcyI6W3siIHQiOlsiZXJyb3IiLCJZb3UgZG8gbm90IGhhdmUgcGVybWlzc2lvbiB0byB2aWV3IHRoaXMgcmVzb3VyY2UuIl19XX0.CSEcAw.pjwXLeSWUsORXR-OU5AfFvq6ESg; HttpOnly; Path=/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: <a href="/">/</a>. If not click the link.
我知道Flask-Security在场景后面使用Flask-Principal进行角色管理(@roles_required等),并且它与数据存储的RoleMixin和UserMixin相关联,非常好。但是,如果没有办法让Flask-Security只允许资源通过而不使用我的JWT标头,那么最好的办法就是建立我自己的装饰器,它使用Flask-Principal来管理角色。
有没有人有这方面的经验?我们的想法是,整个前端可以并且将以我们需要的任何语言构建,这意味着它可能不是Flask的模板/视图,而Flask-Security似乎正在这样做。
感谢任何人提供的任何见解!
答案 0 :(得分:5)
您希望使用HTTP状态代码403来代替重定向。
您最好的选择确实是创建自己的装饰器来管理角色,而完全放弃使用Flask-Security
。
Flask-Security
has mentioned的作者说,有更好的方法来保护API,并且由于不维护该库,这更有意义。
Flask-JWT
或Flask-JWT-Extended
是完成此任务的理想人选。前者将需要更多样板来使事情进展。有stale PR个建议的API支持角色,如果您决定使用Flask-JWT
,则可以使用它来创建自己的装饰器。
Flask-JWT-Extended
文档提出了可能适合您情况的更简单解决方案。对于完整的示例,您应该遵循文档的custom decorators部分,但总而言之,这是修饰符:
from functools import wraps
from flask import jsonify
from flask_jwt_extended import (
verify_jwt_in_request, get_jwt_claims
)
def admin_required(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
verify_jwt_in_request()
claims = get_jwt_claims()
if claims['roles'] != 'admin':
return jsonify(msg='Admins only!'), 403
else:
return fn(*args, **kwargs)
return wrapper
此代码在JWT中查找roles
声明,如果不是admin
,则返回403响应。