2014-12-01 141 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