基于用户角色RESTful路由API

时间:2014-12-01 23:54:26

标签: python json rest flask flask-restful

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

  1. site_admin
  2. department_admin
  3. 基本
  4. 对于任何给定的资源,返回的JSON对象具有基于每个角色的不同密钥集。

    例如,如果您将/ orders命中为“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}
      ]
    }
    

    但是,如果您将/ orders命中为“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')
    

    ......是否有一个共识,哪种方式是RESTful的首选方式?

    非常感谢!

1 个答案:

答案 0 :(得分: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约束。