ASP.NET MVC:Action中的授权 - 建议模式或者这是一种气味?

时间:2009-05-20 18:57:32

标签: asp.net-mvc model-view-controller design-patterns authorization single-responsibility-principle

我有一个使用控制器和操作上的授权属性的ASP.NET MVC应用程序。这种方法运作良好,但出现了新的皱纹。

对象:货件

角色:航运,会计,一般用户

货件在工作流程中移动。在状态A中,它只能由Shipping进行编辑。在状态B中,它只能通过会计编辑。

我有一个ShipmentController和一个Edit Action。我可以使用Authorization属性将Edit操作限制为仅限于这两个角色,但这并不区分Shipment所处的状态。我需要在服务调用之前在操作内部执行一些授权以确定用户是否真的有权执行编辑操作。

所以我有两个问题:

1)在Action中获得授权的好方法。 Controller Action调用服务,然后服务对Shipment对象进行适当的调用(更新数量,更新日期等)。我确信我希望Shipment对象不受任何授权要求的影响。另一方面,如果我希望服务对象知道授权,我没有真正掌握。这有什么好的模式吗?

2)我的问题实际上是设计糟糕的症状吗?我应该有一个StateAShipmentController和StateBShipmentController而不是ShipmentController吗?我没有在Shipment对象中内置任何多态性(状态只是一个枚举),但也许我应该,也许控制器应该反映出来。

我想我会采用更一般的解决方案,而不是针对我的情况。我只是想举例说明这个问题。

谢谢!

4 个答案:

答案 0 :(得分: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 :(得分:2)

您的授权属性可以从操作参数或路线数据中获取货件,然后做出决定。

对于数字1,有许多模式可以在域对象中启用丰富的行为。在double-dispatch中,将对服务抽象(接口)的引用传递给对象上的方法。然后它可以做它的事情。您还可以编写一个应用服务来接收货件并完成工作。

在数字2上,不一定。您可能需要将“上下文装运”的概念抽象为一个服务,以确定您所处的装运环境。但是,在您再次需要它之前,我应该知道这一点。

答案 2 :(得分:1)

您可以查看Rhino.Security,它可以用于在这些场景中实现用户授权。

答案 3 :(得分:1)

除了上面的答案,您还可以返回HttpUnauthorizedResult,而不是为NotAuthorized创建自己的视图。这将重定向到登录页面,其行为与通常的[Authorize]属性

相同