【问题标题】:RESTfully routing an API based on user roles基于用户角色的 RESTful 路由 API
【发布时间】:2015-01-30 02:49:09
【问题描述】:

我正在使用 Flask-RESTful 开发 API,我的应用程序具有三个角色。

  1. site_admin
  2. 部门管理员
  3. 基本

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

例如,如果您以“site_admin”的身份点击 /orders,结果可能如下所示:

{
  "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}
  ]
}

但是,如果您将 /orders 设置为“department_admin”,结果可能如下所示:

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

如果您将 /orders 设置为“基本”,它将是一个非常小的 JSON 响应,如下所示:

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

RESTful 的实现方式是什么?

我可以想出三种方法。

(1) 使用请求参数并对其进行过滤:

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 的首选方式是否存在共识?

非常感谢!

【问题讨论】:

  • 请注意,由于您使用了用户会话,第二个选项并不是真正的 RESTful。 REST API 不应该存储任何客户端状态。相反,您应该要求客户端对他们发送给您的每个请求进行身份验证。
  • @Miguel 好电话。那么,您对 (1) 和 (3) 之间的区别有何看法?
  • 我认为(2)是最好的选择,如果做得对的话。让我在答案中阐述这一点。

标签: python json rest flask flask-restful


【解决方案1】:

您的选项 #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 约束。

【讨论】:

  • 好答案 - 还值得注意的是,提供身份验证并不一定意味着 Basic Auth。你也可以使用HMAC signed tokens
猜你喜欢
  • 1970-01-01
  • 2021-09-20
  • 2018-11-15
  • 1970-01-01
  • 1970-01-01
  • 2016-06-12
  • 2012-01-01
  • 1970-01-01
  • 2018-09-08
相关资源
最近更新 更多