在我的应用程序中,我有两个角色:管理员和用户。管理员可以分配用户以允许他们对特定对象执行特定功能。
由于这超出了SimpleMembership Roles可以提供的范围,我有一个静态帮助方法来检查用户是否有权访问特定的函数:
public static class SecurityCheck
{
public static bool UserHasAccess(int objectId, string functionName)
{
// Decorates the security provider -- gets logged in User ID and calls to a repository to query the database
// ...
}
}
然后我可以在我的视图中使用它来确定是否应该根据对象的ID为该用户呈现特定的函数:
@foreach (var item in Model.FooData)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Notes)
</td>
<td>
@Html.ActionLink("View Data", "View", new { @id = item.Id })
@if (SecurityCheck.UserHasAccess(item.id, "Edit Data"))
{
@Html.ActionLink("Edit Data", "Edit", new {@id = item.Id})
}
@if (SecurityCheck.UserHasAccess(item.id, "Delete"))
{
@Html.ActionLink("Delete", "Delete", new {@id = item.Id})
}
</td>
</tr>
}
我必须相信有更好的方法可以做到这一点,因为对静态方法的每个单独调用都涉及到数据库的单独往返,但我仍然坚持放置代码的最佳位置。我考虑过一些想法:
我倾向于#2。但我仍然觉得我忽略了一个更加坚实的实施。有没有人以前处理类似的事情?
答案 0 :(得分:3)
我认为每个ViewModel都“知道”可以用它做什么,不是吗?所以我们可以隐式显式。 ViewModel可以显式具有CanEdit,CanDelete等属性。
用户界面不应该关心为什么允许或不允许某些操作,它只是以某种方式检查这些属性:
@if (item.CanEdit)
{
@Html.ActionLink("Edit Data", "Edit", new {@id = item.Id})
}
你甚至可以拿出一个帮助器,它将另一个boolean
作为参数来决定是否应该渲染(或启用)控件,但它是次要的:
@Html.SecureActionLink(item.CanEdit, "Edit Data", "Edit", new {@id = item.Id})
这个想法是,UI的责任是不知道如何根据某些业务规则判断是否允许某些内容。
但肯定UI有责任知道在一个ViewModel中呈现的方式和内容不是Editable
或另一个是ReadOnly
(不同的东西可以有不同的状态)。
此外,由于我们正在谈论DDD,我建议不要建模CRUD操作。在一天结束时,DDD是关于无处不在的语言,“创建,更新,删除”几乎不是语言业务真正说的。
因此,您最终会在模型中获得更精确,更有意义的属性/操作,例如CanAccept
(针对订单屏幕)或“CanMakeRefund”(针对付款)。
在构建ViewModel并对其应用安全上下文时,您可以解析/设置这些属性。
希望它有所帮助。
答案 1 :(得分:0)
也许您需要使用SimpleMembership角色:
Assigning Roles with MVC SimpleMembership
在标准MVC会员资格中,您可以使用以下内容:
Roles.AddUserToRole(model.UserName, "Admin");
在你身上查看例如:
if (ViewContext.HttpContext.User.IsInRole("Admin"))