C# 使用ASP.NET标识的动态访问控制
也许我在ASP.NET Identity(2.2.1)的“文档”中忽略了这一点,但我很难理解创建用于管理角色的控制器和接口的意义。我理解管理用户(CRUD+分配角色)的意义,但就角色CRUD而言,对我来说毫无意义,除非有一种方法可以在运行时动态检测控制器的访问(IsInRole)。我有两个问题: 1] 当您必须首先在代码中配置应用程序,以设置C# 使用ASP.NET标识的动态访问控制,c#,asp.net,asp.net-mvc,asp.net-mvc-4,asp.net-identity,C#,Asp.net,Asp.net Mvc,Asp.net Mvc 4,Asp.net Identity,也许我在ASP.NET Identity(2.2.1)的“文档”中忽略了这一点,但我很难理解创建用于管理角色的控制器和接口的意义。我理解管理用户(CRUD+分配角色)的意义,但就角色CRUD而言,对我来说毫无意义,除非有一种方法可以在运行时动态检测控制器的访问(IsInRole)。我有两个问题: 1] 当您必须首先在代码中配置应用程序,以设置Authorize属性,甚至设置应该具有访问权限的角色时,是否有必要将资源和时间用于为角色创建CRUD 及 2] 是否有一种方法可以捕获用户从控制器或控制器
Authorize
属性,甚至设置应该具有访问权限的角色时,是否有必要将资源和时间用于为角色创建CRUD
及
2] 是否有一种方法可以捕获用户从控制器或控制器实例请求操作的时刻,以便可能在该时刻从DB检查权限
根据您的评论,您可以创建一个自定义属性来实现这一点。下面是我如何做到这一点的想法。在OnAuthorization事件中,我将为每个角色创建一个if块。如果用户是该角色的成员,请检查该角色是否有权访问当前控制器。该示例演示了一个名为Admin的角色的想法
using System.Web.Mvc;
using System.Security.Claims;
namespace MyApp.Filters
{
public class CustomAttribute : AuthorizeAttribute
{
private List<string> adminControllers;
public CustomAttribute()
{
this.adminControllers = new List<string>();
//This would be a DB call
this.adminControllers.Add("MyApp.Controllers.AccountController");
this.adminControllers.Add("MyApp.Controllers.AdministrationController");
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
//Get the roles for the current user
var identity = (ClaimsIdentity)filterContext.HttpContext.User.Identity;
var roles = identity.Claims.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value).ToList();
//Check if current user has the Admin role
if (roles.Contains("Admin"))
{
//Check if Admin role has access to current controller
if (this.adminControllers.Contains(filterContext.Controller.ToString()))
{
filterContext.Result = new RedirectResult("~/Home/Error");
}
}
}
}
}
使用System.Web.Mvc;
使用System.Security.Claims;
名称空间MyApp.Filters
{
公共类CustomAttribute:AuthorizeAttribute
{
私有列表管理员控制器;
公共自定义属性()
{
this.adminControllers=新列表();
//这将是一个数据库调用
添加(“MyApp.Controllers.AccountController”);
添加(“MyApp.Controllers.AdministrationController”);
}
授权时的公共覆盖无效(AuthorizationContext filterContext)
{
基于授权(filterContext);
//获取当前用户的角色
var identity=(ClaimsIdentity)filterContext.HttpContext.User.identity;
var roles=identity.Claims.Where(c=>c.Type==ClaimTypes.Role)
.Select(c=>c.Value).ToList();
//检查当前用户是否具有管理员角色
if(roles.Contains(“Admin”))
{
//检查管理员角色是否有权访问当前控制器
if(this.adminControllers.Contains(filterContext.Controller.ToString()))
{
filterContext.Result=新重定向结果(“~/Home/Error”);
}
}
}
}
}
我能找到的最好答案是:
这正是我试图完成的,这证明了我为角色创建CRUD的设计是正确的。此时,由于我可以使用上述方法向控制器动态添加角色,因此我可以动态创建一个角色,然后将其包含在控制器的要求中,以加强访问。您可以在类(控制器)级别甚至方法级别(操作)上使用Authorize attibute,因此用户可以请求控制器,但不能请求所有ActionsRect。这就是我面临的难题。当角色必须硬编码时,为什么要开发一种管理角色的方法呢?感谢Clint的回复。至于#2,没有办法有效地管理动态角色访问,对吗?如果我在数据库的表中配置了权限(考虑组或基于权限的访问),那么每次用户尝试操作或访问控制器时,我都必须点击数据库,对吗?#1,正如您所回答的,您必须硬编码抽象类或控制器上的每个角色。那么,为应用程序中的角色创建CRUD的目的是什么?因此,我对#2感到非常疑惑。企业应用程序中的安全性目的应该是允许管理员为特定用户、组或角色对应用程序的某些区域实施访问控制。如果我不知道存在哪些角色,我如何在我的应用程序中实现它们?@-Keith-对你关于#2的问题是肯定的。对于您关于#1的回复,我只允许管理员访问角色CRUD页面。实际上,我向默认标识数据库添加了一个概要文件表,并为管理员提供了创建概要文件并将其分配给用户的能力。我的个人资料只是一个角色列表。我也做过这样的网站,当用户注册时,会通过编程方式为他们分配默认角色。同样,角色CRUD页面仅供站点管理员使用。因此,可能我问的问题方式不对。将角色分配给用户非常好。我明白了,实际上我已经实现了。问题在于动态定义这些角色有权访问的内容。我实际上考虑过创建一个菜单实体,包括一个包含控制器、操作和角色(IdentityRole列表)的MenuItem实体集合,如果用户处于该角色,他们将有权访问该菜单项。问题是在控制器级别而不是菜单项定义安全性。有道理吗?好吧,也许我读你的问题太快了。我有个主意。我会更新我的答案。