Views 和 ViewModels 如何在 MVC 5 中使用基于声明的授权?
How can Views and ViewModels utilize claims-based authorization in MVC 5?
在我的项目中,我已经实现了 ASP.NET 身份 2.x 以及基于声明的授权和身份验证。
我添加了对声明授权属性 as described here.
的支持
以下是我提出的会 allow/disallow 对员工进行 CRUD 的声明。
public class ResourceClaimTypes
{
public const string CreateEmployee = "urn:company:Employee:Create";
public const string ReadEmployee = "urn:company:Employee:Read";
public const string UpdateEmployee = "urn:company:Employee:Update";
public const string DeleteEmployee = "urn:company:Employee:Delete";
}
一个动作看起来像这样:
[ClaimsAuthorize( ResourceClaimTypes.ReadEmployee )]
public ActionResult Index()
{
return View();
}
我不太明白的是如何在 视图及其视图模型 中使用这些声明。
例如,有一个用于显示员工的视图,它是一个简单的网格。
然后是 编辑 和 创建 员工的视图。
视图和视图模型现在应该能够根据用户的要求隐藏或显示 Save/Update/Delete 按钮。
处理意见:
如果存在 ReadEmployee 声明,Index -> 应显示所有员工,否则视图仍应可访问,但会显示一条消息 "No premission to view employees".
Create/Edit -> 用户应该仍然可以导航到这些视图,但是 "Create"/"Save" 按钮不应该可见。
删除 -> 应隐藏所有 "Delete" 按钮。
底线是,视图应该可以访问,但是 Create/Save 按钮应该 隐藏。
如何做到?
* 更新/我的解决方案 *
我就是这样完成的。
根据 Derek 的建议,我使用了基于 Action/Resource 的身份验证。除了 ASP.NET Identity,我还实现了 IUserClaimStore 接口以从数据库中获取声明。
视图和视图模型 (!) 不包含任何类似 CanRead、CanWrite 的内容!
我正在使用 KendoUI 并为按钮创建了一个扩展方法。
在扩展方法中,我可以访问自定义 ResourceAuthorizationManager(请参阅 Dominik Baier 的博客)。所以在创建按钮时,我可以调用 HttpContaxtBase.CheckAccess(...) 来确定按钮是否应该是 enabled/visible。
我唯一需要的是告诉扩展方法要检查访问权限的 action/resource 组合。
剃刀示例:
@Html.LinkButton(Action.Create, Resource.Employee)
这就是视图中显示(或不显示)显示 "Create" 并指向 Employee 控制器的 Create 视图的按钮所需的全部内容。
非常干净,恕我直言。
您可以在项目的任何位置访问当前用户的声明,视图也不例外。只需将当前用户的身份转换为 claimsIdentity
即可访问用户的声明:
var claims= ((ClaimsIdentity)HttpContext.Current.User.Identity).Claims;
你也可以为此写一个扩展方法:
public static bool CanEdit(this IIdentity identity)
{
return identity.IsAuthenticated
&& identity is ClaimsIdentity
&& ((ClaimsIdentity)identity).HasClaim(x =>
x.Type == "EditClaim" && x.Value == "true");
}
那么你可以很容易地写出这样的代码:
if(HttpContext.Current.User.Identity.CanEdit())
{
//your code
}
但即使您可以直接检查视图中的声明,也可以考虑检查控制器中的声明,并通过视图模型将简单的 true 或 false 值发送到您的视图以获得更好的方法。
因为我们不想将我们的逻辑混入视图中。最好在控制器中检查权限。考虑一下:
class PrivilegesViewModel
{
public bool CanEdit{get;set;}
public bool CanRead{get;set;}
// and so on
}
class PostViewModel
{
// our model data
public PrivilegesViewModel Privileges{get;set;}
}
在你的控制器中:
public ActionResult Edit(int id)
{
PostViewModel model=_postManager.Get(id);
model.Privileges=new PrivilegesViewModel
{
CanEdit=HttpContext.Current.User.Identity.CanEdit(),
// and so on
}
return View(model);
}
现在在您的视图中只需检查 bool 值;
@if(model.Privileges.CanEdit)
{
// print the button
}
你应该看看 Thinktecture 的 Dominic Baier 的产品,这样的东西。
下面的文章将解释如何优雅地实现您想要的东西。
他们那里有示例 Git Hub 仓库。
** 编辑 **
这是您需要遵循的 link 到 GitHub 示例。
在我的项目中,我已经实现了 ASP.NET 身份 2.x 以及基于声明的授权和身份验证。 我添加了对声明授权属性 as described here.
的支持以下是我提出的会 allow/disallow 对员工进行 CRUD 的声明。
public class ResourceClaimTypes
{
public const string CreateEmployee = "urn:company:Employee:Create";
public const string ReadEmployee = "urn:company:Employee:Read";
public const string UpdateEmployee = "urn:company:Employee:Update";
public const string DeleteEmployee = "urn:company:Employee:Delete";
}
一个动作看起来像这样:
[ClaimsAuthorize( ResourceClaimTypes.ReadEmployee )]
public ActionResult Index()
{
return View();
}
我不太明白的是如何在 视图及其视图模型 中使用这些声明。 例如,有一个用于显示员工的视图,它是一个简单的网格。 然后是 编辑 和 创建 员工的视图。
视图和视图模型现在应该能够根据用户的要求隐藏或显示 Save/Update/Delete 按钮。
处理意见:
如果存在 ReadEmployee 声明,Index -> 应显示所有员工,否则视图仍应可访问,但会显示一条消息 "No premission to view employees".
Create/Edit -> 用户应该仍然可以导航到这些视图,但是 "Create"/"Save" 按钮不应该可见。
删除 -> 应隐藏所有 "Delete" 按钮。
底线是,视图应该可以访问,但是 Create/Save 按钮应该 隐藏。
如何做到?
* 更新/我的解决方案 *
我就是这样完成的。 根据 Derek 的建议,我使用了基于 Action/Resource 的身份验证。除了 ASP.NET Identity,我还实现了 IUserClaimStore 接口以从数据库中获取声明。
视图和视图模型 (!) 不包含任何类似 CanRead、CanWrite 的内容! 我正在使用 KendoUI 并为按钮创建了一个扩展方法。
在扩展方法中,我可以访问自定义 ResourceAuthorizationManager(请参阅 Dominik Baier 的博客)。所以在创建按钮时,我可以调用 HttpContaxtBase.CheckAccess(...) 来确定按钮是否应该是 enabled/visible。
我唯一需要的是告诉扩展方法要检查访问权限的 action/resource 组合。
剃刀示例:
@Html.LinkButton(Action.Create, Resource.Employee)
这就是视图中显示(或不显示)显示 "Create" 并指向 Employee 控制器的 Create 视图的按钮所需的全部内容。 非常干净,恕我直言。
您可以在项目的任何位置访问当前用户的声明,视图也不例外。只需将当前用户的身份转换为 claimsIdentity
即可访问用户的声明:
var claims= ((ClaimsIdentity)HttpContext.Current.User.Identity).Claims;
你也可以为此写一个扩展方法:
public static bool CanEdit(this IIdentity identity)
{
return identity.IsAuthenticated
&& identity is ClaimsIdentity
&& ((ClaimsIdentity)identity).HasClaim(x =>
x.Type == "EditClaim" && x.Value == "true");
}
那么你可以很容易地写出这样的代码:
if(HttpContext.Current.User.Identity.CanEdit())
{
//your code
}
但即使您可以直接检查视图中的声明,也可以考虑检查控制器中的声明,并通过视图模型将简单的 true 或 false 值发送到您的视图以获得更好的方法。
因为我们不想将我们的逻辑混入视图中。最好在控制器中检查权限。考虑一下:
class PrivilegesViewModel
{
public bool CanEdit{get;set;}
public bool CanRead{get;set;}
// and so on
}
class PostViewModel
{
// our model data
public PrivilegesViewModel Privileges{get;set;}
}
在你的控制器中:
public ActionResult Edit(int id)
{
PostViewModel model=_postManager.Get(id);
model.Privileges=new PrivilegesViewModel
{
CanEdit=HttpContext.Current.User.Identity.CanEdit(),
// and so on
}
return View(model);
}
现在在您的视图中只需检查 bool 值;
@if(model.Privileges.CanEdit)
{
// print the button
}
你应该看看 Thinktecture 的 Dominic Baier 的产品,这样的东西。
下面的文章将解释如何优雅地实现您想要的东西。
他们那里有示例 Git Hub 仓库。
** 编辑 **
这是您需要遵循的 link 到 GitHub 示例。