ASP MVC 5 - 扩展身份 2.0

ASP MVC 5 - Extending Identity 2.0

我有以下 ApplicationUser class,有没有办法添加声明或扩展身份,以便我可以通过执行以下操作检查用户是否在项目组中:User.Identity.IsInProjectGroup(1)

目前我必须继续进入数据库获取用户,然后调用 IsInProjectGroup 方法。

public class ApplicationUser : IdentityUser
{
    public ApplicationUser()
    {
        Id = Guid.NewGuid().ToString();
        Groups = new Collection<Group>();
    } 

    public string FirstName { get; set; }
    public ICollection<Group> Groups { get; set; }

    public bool IsInProjectGroup(int projectId)
    {
        return Groups.Any(g => g.Projects.Select(x => x.Id).Contains(projectId));

    }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
       var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);

       // how do you add claim???
       userIdentity.AddClaim(new Claim("Group", ???));

       return userIdentity;
     }

 }

有没有办法添加调用方法的声明,或者有其他方法可以实现这一点?

我正在考虑如下扩展,但不确定如何在我的 ApplicationUser class 中添加这样的声明以及如何在下面的扩展方法中检查声明:

namespace App.Extensions
{
   public static class IdentityExtensions
   {
       public static bool IsInProjectGroup(this IIdentity identity, int projectId)
       {
           // how would i do the check here???
       }
   }
}

这是一个简单的例子。

首先创建一个常量用作声明的键

public class Constants { 
    public class Security {
        public class ClaimTypes
            public const string ProjectGroups = "ProjectGroups";
        }
    }
} 

然后您可以在创建身份时创建声明

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager) {
   var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
   // how do you add claim???
   if(Groups.Any()) { //assuming this is a navigation property
       //create a claim type/name/key
       //replace with you desired key. Store in a constant for later use
       var claimName = Constants.Security.ClaimTypes.ProjectGroup; 
       //create claims from current groups.
       var claims = Groups.SelectMany(g => g.Projects.Select(x => x.Id))
           .Select(id => new System.Security.Claims.Claim(claimName, id.ToString()));
       userIdentity.AddClaims(claims);
   }
   return userIdentity;
 }

对于检索,您可以创建自己的扩展方法来检查声明本身内的组,而不是访问数据库。

public static class IdentityExtensions {
    public static bool IsInProjectGroup(this IIdentity identity, int projectId) {
       // how would i do the check here???
       if(identity != null) {
            var claimsIdentity = identity as ClaimsIdentity;
            if (claimsIdentity != null) {
                return claimsIdentity
                    .FindAll(Constants.Security.ClaimTypes.ProjectGroups)
                    .Any(claim => claim.Value == projectId.ToString());
            }
       }
       return false;
    }
}