【问题标题】:Where should access control logic live in MVC?访问控制逻辑在 MVC 中应该放在哪里?
【发布时间】:2015-12-01 04:20:42
【问题描述】:

我正在学习使用 MVC 和代码优先实体框架(使用 razor)的 ASP.NET。我一直在发现很多关于该主题的相互矛盾的信息,我想我会求助于 SO 社区来尝试澄清一些事情。

从模型到控制器再到视图,访问逻辑应该放在哪里?例如(为这篇文章简化):

public class EmployeeController : Controller
{
    private Repo _repo;

    [HttpGet]
    public ActionResult Create(int id)
    {
        Business business = _repo.FindBusiness(id);
        if (CurrentUser.UserId == business.GeneralManager.UserId ||
            CurrentUser.Father.UserId == business.Owner.UserId)
        {
            Employee employee = new Employee();
            employee.Business = business;
            return View();
        }
    }
    [HttpPost]
    public ActionResult Create(Employee employee)
    {
        Business business = _repo.FindBusiness(employee.business.ID);
        if (CurrentUser.UserId == business.GeneralManager.UserId ||
            CurrentUser.Father.UserId == business.Owner.UserId)
        {
            _repo.Save(employee);
            Return Redirect(...);
        }
    }
}

然后,如果当前用户是企业的总经理或者他的父亲拥有该场所,那么我希望当前用户能够创建新企业。我在这里要指出的是,它不依赖于用户的角色,而是依赖于他们为什么可以采取行动的一些业务逻辑。

同样,我希望能够基于相同的条件在视图中显示或隐藏链接,例如:

...
@if (CurrentUser.UserId == business.GeneralManager.UserId ||
     CurrentUser.Father.UserId == business.Owner.UserId)
     {
        @Html.ActionLink(...)
     }
...

我绝对不想这样做。我的问题是:如果可以将访问逻辑捆绑为单个方法,那么该方法在 mvc 中“属于”哪里?它应该是 ViewModel 的只读属性吗?应该有一些静态访问控制器吗?模型本身的一部分?感谢您的关注!

【问题讨论】:

标签: asp.net asp.net-mvc razor


【解决方案1】:

您应该为此使用ActionFilters,查看this 示例。

也请查看this 的答案以获得授权。

编写完 ActionFilter 逻辑后,您的控制器将如下所示:

public class EmployeeController : Controller
{
    private Repo _repo;

    [CustomActionFilter] //your ACL logic will be here.
    [HttpGet]
    public ActionResult Create(int id)
    {
       //no acl logic in here.
    }

    [CustomActionFilter] //your ACL logic will be here.
    [HttpPost]
    public ActionResult Create(Employee employee)
    {
       //no acl logic in here.
    }
}

ActionFilters 也可以应用于控制器级别。

【讨论】:

  • 感谢您的回复。我对这有什么帮助有点困惑。所以对于我在控制器上的 每个 操作,我必须实现一个自定义 ActionFilter 来保存访问控制逻辑?这似乎太过分了。
  • 对不起,我不明白你的问题。您也可以在 Controller 级别使用 ActionFilter,无需在每个 Action 中重复。
  • 我不明白的是如何创建自定义 ActionFilter 有助于从控制器中删除“if”的内容,即 (CurrentUser.UserId == busines.....)这样我就可以在相同的条件下有条件地从视图中隐藏 ActionLink。如果 CanCreate() 的条件与 CanView() 或 CanModifySalary() 不同,那么我不需要为每个操作创建自定义 ActionFilter 吗??
  • @Ang 是的,您将为每个操作使用 ActionFilter。但是,通常您的用户分为几类:[普通用户、管理员等]。因此,您不需要编写许多 CustomActionFIlters,每个类别(普通用户、管理员等)只需一个。
猜你喜欢
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 2017-04-29
  • 2012-01-24
  • 1970-01-01
  • 2017-04-19
  • 2016-12-18
  • 2014-10-26
相关资源
最近更新 更多