C# 如何从HttpContext访问角色对象,或者更具体地说,如何从自定义授权属性访问角色对象? 背景

C# 如何从HttpContext访问角色对象,或者更具体地说,如何从自定义授权属性访问角色对象? 背景,c#,asp.net-identity-2,asp.net-mvc-5.2,C#,Asp.net Identity 2,Asp.net Mvc 5.2,我想根据他们的ApplicationRolesRoleClaims授权ApplicationUser。我想这样实施: public class RoleClaimAuthorizeAttribute : AuthorizeAttribute { public RoleClaim RoleClaim { get; set; } protected override bool AuthorizeCore(HttpContextBase httpContext) {

我想根据他们的
ApplicationRole
s
RoleClaim
s授权
ApplicationUser
。我想这样实施:

public class RoleClaimAuthorizeAttribute : AuthorizeAttribute
{
    public RoleClaim RoleClaim { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        foreach (ApplicationRole role in Roles)
        {
            if ((RoleClaim & role.Claims) > 0)
            {
                return true;
            }
        }
        return false;
    }
}
    [RoleClaimAuthorize(RoleClaim = 
        RoleClaim.CanCreateRoles | 
        RoleClaim.CanReadRoles | 
        RoleClaim.CanDeleteRoles | 
        RoleClaim.CanUpdateRoles
    )]
    //
    // GET: /Roles/
    public ActionResult Index()
    {
        return View(_roleManager.Roles);
    }
然后我可以这样装饰控制器动作:

public class RoleClaimAuthorizeAttribute : AuthorizeAttribute
{
    public RoleClaim RoleClaim { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        foreach (ApplicationRole role in Roles)
        {
            if ((RoleClaim & role.Claims) > 0)
            {
                return true;
            }
        }
        return false;
    }
}
    [RoleClaimAuthorize(RoleClaim = 
        RoleClaim.CanCreateRoles | 
        RoleClaim.CanReadRoles | 
        RoleClaim.CanDeleteRoles | 
        RoleClaim.CanUpdateRoles
    )]
    //
    // GET: /Roles/
    public ActionResult Index()
    {
        return View(_roleManager.Roles);
    }

问题: 我遇到的问题是,我能找到的任何从自定义授权属性访问
ApplicationUser
ApplicationRole
s的方法都会返回
ApplicationRole的字符串数组。Name
不是
ApplicationRole
的数组,因此我无法访问
ApplicationRole。声明
。我还使用Unity而不是Owin来处理
ApplicationRoleManager
,因此我无法通过
HttpContext.Current.GetOwinContext().Get()请求
ApplicationRoleManager

那么,如何才能获得当前用户的
ApplicationRole
对象集合,从而获得
ApplicationRole.Claims

或者,如果这是一个更合适的解决方案,我如何在
HttpContext
中存储当前
ApplicationUser
ApplicationRole
s
RoleClaim
s的字符串数组,就像存储角色一样?我知道我的授权属性在这种情况下无法正常工作,但我仍然可以处理这种情况


相关类 应用程序用户 应用程序角色管理器
公共类应用程序RoleManager:RoleManager
{
公共应用程序角色管理器(IRoleStore存储):基本(存储)
{
}
}

如果您在Unity中注册了角色管理器,只需调用以下方法,您就可以随时随地检索角色管理器,包括自定义属性:

var roleManager = DependencyResolver.Current.GetService<ApplicationRoleManager>();
现在,当用户登录时,
RoleClaims
作为声明添加。您可以在属性中检索它们,如下所示:

public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
    private readonly ApplicationRoleManager _roleManager;

    public ApplicationSignInManager(ApplicationUserManager userManager, 
        IAuthenticationManager authenticationManager,
        ApplicationRoleManager rolemanager)
            : base(userManager, authenticationManager)
    {
         //inject the role manager to the sign in manager
        _roleManager=rolemanager;
    }

    public override async Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
    {
        var ident= await user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
        // add your custom claims here
        var userRoles=user.Roles.Select(r=>r.RoleId);
        ident.AddClaims(_roleManager.Roles.Where(r => userRoles.Any(ur => ur == r.Id))
            .Select(r=>r.Claims).ToList()
            .Select(c => new Claim("RoleClaims", c.ToString())));
        return ident;
    }
}
public class RoleClaimAuthorizeAttribute : AuthorizeAttribute
{
    public RoleClaim RoleClaim { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        foreach (var claims in GetClaims(httpContext.User.Identity as ClaimsIdentity))
        {
            if ((RoleClaim & claims) > 0)
            {
                return true;
            } 
        }
        return false;
    }
    private IEnumerable<RoleClaim> GetClaims(ClaimsIdentity ident)
    {
        return ident==null
            ? Enumerable.Empty<RoleClaim>()
            : ident.Claims.Where(c=>c.Type=="RoleClaims")
                .Select(c=>(RoleClaim)Enum.Parse(typeof(RoleClaim), c.Value)); 
    }
}
公共类RoleClaimAuthorizeAttribute:AuthorizeAttribute
{
公共RoleClaim RoleClaim{get;set;}
受保护的覆盖bool AuthorizeCore(HttpContextBase httpContext)
{
foreach(GetClaims中的var声明(httpContext.User.Identity as ClaimsIdentity))
{
如果((RoleClaim&索赔)>0)
{
返回true;
} 
}
返回false;
}
私人IEnumerable GetClaims(索赔实体标识)
{
返回标识==null
?可枚举。空()
:ident.Claims.Where(c=>c.Type==“RoleClaims”)
.Select(c=>(RoleClaim)Enum.Parse(typeof(RoleClaim),c.Value));
}
}

感谢您提供的替代解决方案,它比我想象的要好得多。从
ApplicationSignInManager
中的
CreateUserIdentityAsync
下的
ident.AddClaims
行出现问题。异常如下:无法创建类型为“
ApplicationUserRole
”的常量值。在此上下文中仅支持基元类型或枚举类型。进行了一点挖掘,看起来这是来自Linq查询的where一半,我自己在寻找如何修复它,但我认为我应该发布。不幸的是,这并不能解决问题。以下代码是导致异常的原因,只是它仅在枚举可枚举项时才会抛出:
\u rolemanger.Roles.Where(r=>user.Roles.Any(ur=>ur.RoleId==r.Id))
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
    private readonly ApplicationRoleManager _roleManager;

    public ApplicationSignInManager(ApplicationUserManager userManager, 
        IAuthenticationManager authenticationManager,
        ApplicationRoleManager rolemanager)
            : base(userManager, authenticationManager)
    {
         //inject the role manager to the sign in manager
        _roleManager=rolemanager;
    }

    public override async Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
    {
        var ident= await user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
        // add your custom claims here
        var userRoles=user.Roles.Select(r=>r.RoleId);
        ident.AddClaims(_roleManager.Roles.Where(r => userRoles.Any(ur => ur == r.Id))
            .Select(r=>r.Claims).ToList()
            .Select(c => new Claim("RoleClaims", c.ToString())));
        return ident;
    }
}
public class RoleClaimAuthorizeAttribute : AuthorizeAttribute
{
    public RoleClaim RoleClaim { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        foreach (var claims in GetClaims(httpContext.User.Identity as ClaimsIdentity))
        {
            if ((RoleClaim & claims) > 0)
            {
                return true;
            } 
        }
        return false;
    }
    private IEnumerable<RoleClaim> GetClaims(ClaimsIdentity ident)
    {
        return ident==null
            ? Enumerable.Empty<RoleClaim>()
            : ident.Claims.Where(c=>c.Type=="RoleClaims")
                .Select(c=>(RoleClaim)Enum.Parse(typeof(RoleClaim), c.Value)); 
    }
}