10

我有一個ASP.NET MVC應用程序使用控制器和操作上的授權屬性。這一直運行良好,但出現了新的皺紋。ASP.NET MVC:授權內部的行動 - 建議模式或這是一種氣味?

對象:裝運

角色:航運,會計,一般用戶

貨件通過工作流程移動。在狀態A中,只能通過運輸進行編輯。在狀態B中,只能通過會計編輯。

我有一個ShipmentController和一個編輯動作。我可以通過授權屬性將Edit動作限制爲僅限於這兩種角色,但這並不能區分Shipment所處的狀態。我需要在服務調用之前在動作中執行一些授權,以確定用戶真的有權執行編輯操作。

所以我留下了兩個問題:

1)請告訴我一個好辦法,有一個動作裏面授權。 Controller Action調用一個服務,然後服務對Shipment對象進行適當的調用(更新數量,更新日期等)。我知道我希望Shipment對象不受任何授權要求的限制。另一方面,如果我希望服務對象知道授權與否,我沒有真正的把握。有沒有什麼好的模式?

2)我的問題實際上是不良設計的症狀嗎?我應該有一個StateAShipmentController和StateBShipmentController,而不是ShipmentController?我沒有在Shipment對象中構建任何多態(狀態只是一個枚舉),但也許我應該,也許控制器應該反映這一點。

我想我是更多的一般解決方案後,而不是一個具體的情況。我只是想舉一個例子來說明這個問題。

謝謝!

+0

爲什麼不爲自己的貨件相關內容創建自己的[授權]行爲篩選器? – 2009-05-20 20:45:55

+0

構建你自己的[Authorize]過濾器將是一個非常非常糟糕的主意,它是ASP.NET MVC開發團隊真的非常強烈地沮喪的原因之一 – 2009-05-20 21:25:51

回答

2

您的授權屬性可以從操作參數或路線數據中獲取貨件,然後做出決定。

對於數字1,有許多模式可以在域對象中實現豐富的行爲。在double-dispatch中,您將對服務抽象(接口)的引用傳遞給對象上的方法。然後它可以做到這一點。您也可以編寫一個應用程序服務來接收貨件並完成工作。

在數字2上,不一定。您可能需要將「上下文裝運」的概念抽象爲一個服務,以找出您所處的裝運環境。但是,我會YAGNI,直到您再次需要它。

1

您可以看看Rhino.Security,它可以用於在這些情況下實現用戶授權。

3

我沒有看到Action方法在進行進一步的授權檢查時出現問題。您可以利用角色提供商爲您尋找的細粒度授權。請原諒我的語法 - 這可能很糟糕,我還沒有測試過。

[Authorize(Roles="Shipping, Accounting")] 
public ActionResult Edit(int id) 
{ 
    Shipment shipment = repos.GetShipment(id); 


    switch (shipment.State) 
    { 
     case ShipmentState.A: 
     if (Roles.IsUserInRole("Shipping")) 
       return View(shipment); 
     else 
       return View("NotAuthorized"); 
     break; 
     case ShipmentState.B: 
     if (Roles.IsUserInRole("Accounting")) 
       return View(shipment); 
     else 
       return View("NotAuthorized"); 
     break; 
     default: 
       return View("NotAuthorized"); 
    } 
} 
1

除了上面的答案,您可以返回一個HttpUnauthorizedResult,而不是創建自己的NotAuthorized視圖。這將重定向到登錄頁面,其行爲與通常的[授權]屬性相同