10

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

对象:装运

角色:运输、会计、一般用户

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

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

所以我有两个问题:

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

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

我想我正在寻求更通用的解决方案,而不是针对我的案例的特定解决方案。我只是想提供一个例子来说明这个问题。

谢谢!

4

4 回答 4

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");
     }
}
于 2009-05-21T14:18:19.347 回答
2

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

对于第 1 点,有许多模式可以在域对象中启用丰富的行为。在双重分派中,您将对服务抽象(接口)的引用传递给对象上的方法。然后它可以做它的事情。您还可以编写一个应用程序服务来接收 Shipment 并完成工作。

2号,不一定。您可能需要将“上下文 Shipment”的概念抽象为一项服务,以确定您所处的 Shipment 上下文。但我会使用 YAGNI 直到您再次需要它。

于 2009-05-20T19:01:55.490 回答
1

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

于 2009-05-20T19:06:36.743 回答
1

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

于 2009-05-22T13:15:00.430 回答