2014-12-01 107 views
3

我正在使用Flask-RESTful开发API,并且我的应用程序有三个角色。基于用户角色RESTfully路由API

  1. site_admin
  2. department_admin
  3. 基本

对于任何给定的资源,JSON对象返回都有一套不同的基于每个角色的键。

例如,如果你打/订单为“site_admin”,其结果可能是这样的:

{ 
    "orders": [ 
    {"id": 1, "user": "foo", "paid": True, "department": "A", "code": 456}, 
    {"id": 2, "user": "bar", "paid": False, "department": "A", "code": 567}, 
    {"id": 3, "user": "meh", "paid": False, "department": "B", "code": 678} 
    ] 
} 

但是,如果你打/订单为“department_admin”,其结果可能是这样的:

{ 
    "orders": [ 
    {"id": 3, "user": "meh", "paid": False} 
    ] 
} 

如果你打/订单为 “基本”,它会是这样一个很小的JSON响应:

{ 
    "orders": [ 
    {"id": 2, "paid": True} 
    ] 
} 

实现这个的RESTful方式是什么?

我可以想出三种方法。

(1)利用上一个请求Arg和过滤:

class Orders(restful.Resource): 
    def get(self): 
    if request.args['role'] == 'site_admin': 
     return admin_JSON_response() 
    elif request.args['role'] == 'department_admin': 
     return dept_admin_JSON_response() 
    else: 
     return basic_JSON_response() 

api.add_resource(Orders, '/orders') 

(2)的会话对象过滤:

class Orders(restful.Resource): 
    def get(self): 
    if session['role'] == 'site_admin': 
     return admin_JSON_response() 
    elif session['role'] == 'department_admin': 
     return dept_admin_JSON_response() 
    else: 
     return basic_JSON_response() 

api.add_resource(Orders, '/orders') 

(3)具有用于每个角色不同的路线:

class OrdersSiteAdmin(restful.Resource): 
    def get(self): 
    return admin_JSON_response() 
api.add_resource(OrdersSiteAdmin, '/orders_site_admin') 

class OrdersDeptAdmin(restful.Resource): 
    def get(self): 
    return dept_admin_JSON_response() 
api.add_resource(OrdersDeptAdmin, '/orders_dept_admin') 

class OrdersBasic(restful.Resource): 
    def get(self): 
     return basic_JSON_response() 
api.add_resource(OrdersBasic, '/orders_basic') 

...有什么共识,哪个是首选的方式RESTfully?

非常感谢!

+0

请注意,由于您使用了用户会话,因此第二个选项不是真正的RESTful。 REST API不应该存储任何客户端状态。相反,您应该要求客户端验证他们发送给您的每个请求。 – Miguel 2014-12-02 15:38:08

+0

@Miguel很好的电话。那么你对(1)和(3)之间的区别有什么想法? – SeanPlusPlus 2014-12-02 20:44:32

+0

我认为(2)是最好的选择,如果做得对。让我在回答中提出这个问题。 – Miguel 2014-12-02 21:50:11

回答

4

您的选项#2违反了“无状态”约束,在REST API中使用用户会话不是一个好主意,相反,您应该要求客户端为每个请求提供身份验证。

我们假设您修复了#2而不是用户会话,您现在有一个current_user变量,该变量在验证期间填充。然后,可以按如下方式重写例如:

class Orders(restful.Resource): 
    def get(self): 
    if current_user.role == 'site_admin': 
     return admin_JSON_response() 
    elif current_user.role == 'department_admin': 
     return dept_admin_JSON_response() 
    else: 
     return basic_JSON_response() 

api.add_resource(Orders, '/orders') 

让我们看看你的三个选项中的一个接一个:

  • (1)指定的查询字符串的作用,这将使任何用户请求任何表示,只需传递所需的角色。但为什么把角色放在查询字符串中呢?我假设你会验证你的用户,所以知道你的用户你也知道这个角色。这似乎是不必要的,并会给你额外的验证工作。

  • (3)为每个角色创建不同的资源。再一次,您必须确保“基本”用户无权访问适用于更高角色的两个URL,因此您还需要在此处进行一些验证工作。(2)假定用户数据库存储每个用户的角色,因此一旦用户通过了认证,他/她的角色的正确表示将根据所分配的角色返回。我认为这是最好的选择,因为用户根本无法破解他们不允许看到的数据。

说到RESTful,我也看看你的表示,这可以改进。考虑实施到其他资源的链接,而不是提供ID,以符合HATEOAS约束。

+0

很好的答案。也感谢链接到HATEOAS。 – SeanPlusPlus 2014-12-02 22:17:09

+0

好的答案 - 值得注意的是,提供身份验证并不一定意味着'基本身份验证'。您也可以使用[HMAC签名令牌](https://stackoverflow.com/questions/26999791/flask-restful-destroy-user-token)。 – 2014-12-03 02:28:50