Asp.net mvc ASP.NETMVC:操作建议模式中的授权还是这是一种气味?

Asp.net mvc ASP.NETMVC:操作建议模式中的授权还是这是一种气味?,asp.net-mvc,model-view-controller,design-patterns,authorization,single-responsibility-principle,Asp.net Mvc,Model View Controller,Design Patterns,Authorization,Single Responsibility Principle,我有一个ASP.NET MVC应用程序,在控制器和操作上使用授权属性。这一直很有效,但出现了新的问题 对象:装运 角色:运输、会计、一般用户 装运将在工作流中移动。在状态A中,只能通过配送进行编辑。在状态B中,只能通过会计进行编辑 我有一个ShipmentController和一个编辑操作。我可以设置一个Authorization属性,将编辑操作仅限于这两个角色,但这并不能区分装运处于哪个状态。在服务调用之前,我需要在操作内部进行一些授权,以确定用户是否真正有权执行编辑操作 我还有两个问题: 1

我有一个ASP.NET MVC应用程序,在控制器和操作上使用授权属性。这一直很有效,但出现了新的问题

对象:装运

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

装运将在工作流中移动。在状态A中,只能通过配送进行编辑。在状态B中,只能通过会计进行编辑

我有一个ShipmentController和一个编辑操作。我可以设置一个Authorization属性,将编辑操作仅限于这两个角色,但这并不能区分装运处于哪个状态。在服务调用之前,我需要在操作内部进行一些授权,以确定用户是否真正有权执行编辑操作

我还有两个问题:

1) 在操作中拥有授权的好方法是什么。控制器操作调用服务,然后服务对发货对象进行适当的调用(更新数量、更新日期等)。我确信我希望装运对象不受任何授权要求的影响。另一方面,我不知道我是否希望服务对象知道授权。这有什么好的模式吗

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

我想我想要的是更一般的解决方案,而不是针对我的案例的具体解决方案。我只是想举个例子来说明这个问题


谢谢

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

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


在2号上,不一定。您可能需要将“上下文装运”的概念抽象到一个服务中,以确定您所处的装运上下文。但在您再次需要它之前,我会一直这么做。

您可以看看,它可以用于在此类场景中实现用户授权

我认为操作方法在其中执行进一步的授权检查没有问题。您可以利用角色提供程序获得所需的细粒度授权。请原谅我的语法在这里-它可能是粗糙的,我还没有测试这个

[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");
     }
}

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

为什么不为与装运相关的内容创建自己的[Authorize]类操作筛选器?构建自己的[Authorize]筛选器将是一个非常非常糟糕的主意,而ASP.NET MVC开发团队对此非常坚决discouraged@Josh; 我不同意。这不是一个“非常非常糟糕的主意”,只是一个应该谨慎对待的主意。我还没有看到任何关于阻止它的公开文章,更不用说一些“真的”和“强烈的”。据我所知,唯一真正的“gotcha”是您希望从框架提供的Authorize属性继承,因为这样可以确保在正确的位置可靠地触发它。@Paul-关于“gotcha”的观点很好。在去年的Hanselmann、Haack、Guthrie MVC书籍中,我记得他们说过,他们强烈反对创建自己的auth过滤器。回想起来,他们很可能想提出与你相同的观点。虽然这是一个“简单”的解决方案,但有点难闻。对控制器上的授权进行硬编码违反了SRP,至少应该重构到自己的类中。这个示例几乎需要一个状态模式实现。呵呵,是的,确实如此!虽然过于简单,但我想确保我解决了OP的问题,而不是陷入细节。