asp.net Identity如何生成用户声明



我有一个用Typescript实现的单页应用程序的场景,它使用oidc-client从使用IdentityServer4的AspNet Core应用程序中获取id_token和access_token。

在身份服务器上,我也使用identity with EntityFramework,这样我就可以检索User和他们的配置文件来生成声明,等等。

我面临着一个奇怪的情况,例如我正在为用户更新FirstName,它在数据库中得到正确更新,但是当生成用户级声明(given_name, family_name, nameemail)时,given_name没有用新名称更新,因此发布的id_token不包含声明中更新的信息。

我有这样的东西:

public class AspNetIdentityProfileService : IProfileService
{
  private readonly UserManager<User> _userManager;
  private readonly IUserRepository _userRepository;
  public AspNetIdentityProfileService(UserManager<User> userManager, IUserRepository userRepository)
  {
     _userManager = userManager;
     _userRepository = userRepository;
  }
  // some code where I generate a List<Claim> calling below method
  private async Task<IEnumerable<Claim>> GetUserLevelClaimsAsync(User user)
  {
     //user contains the updated info because it comes from DB.
     List<Claim> userClaims = new List<Claim>();
     var standardClaims = await _userManager.GetClaimsAsync(user); //has old values
     userClaims.AddRange(standardClaims);
     userClaims.Add(new Claim(JwtClaimTypes.Role, user.Role.ToString().ToLowerInvariant()));
     return userClaims;
  }
}

为什么await _userManager.GetClaimsAsync(user);忽略了用户的更新信息?从哪里获得旧信息?我重新启动了应用程序,删除了浏览器cookie,以防它存储在身份服务器为单点登录目的发布的cookie中。但是我仍然不知道旧的信息缓存在哪里。

更新1 :这是User模型。

public class User : IdentityUser
{
    //Extend properties
    public DateTime CreatedOn { get; set; }
    public DateTime ModifiedOn { get; set; }
    public Guid? PrimaryBusinessId { get; set; }
    public Business PrimaryBusiness { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName
    {
        get
        {
            return string.Join(" ", FirstName, LastName);
        }
    }
    public DateTime? LastLoggedInOn { get; set; }
    public UserRole Role { get; set; }
    public List<UserBusiness> UserBusinesses { get; set; }
}

更新2 :有一个明显的解决方法,那就是手动添加来自User属性的声明,而不是依赖于Identity的UserManager。但是问题仍然存在,为什么userManager不检索数据库中更新的值?它在哪里找到检索到的旧值?

    private IEnumerable<Claim> GetUserLevelClaims(User user)
    {
        List<Claim> userClaims = new List<Claim>();
        //var standardClaims = await _userManager.GetClaimsAsync(user); //does not retrieve updated fields
        userClaims.Add(new Claim(JwtClaimTypes.Name, user.FullName));
        userClaims.Add(new Claim(JwtClaimTypes.FamilyName, user.LastName));
        userClaims.Add(new Claim(JwtClaimTypes.GivenName, user.FirstName));
        userClaims.Add(new Claim(JwtClaimTypes.Email, user.Email));
        userClaims.Add(new Claim(JwtClaimTypes.Role, user.Role.ToString().ToLowerInvariant()));
        return userClaims;
    }

您需要告诉IProfileService从哪里获得索赔。

基本上,AspNetCore.IdentityuserManager只会获得该用户的相关声明。也就是IdentityUser.Claims。"旧值"仍然存在于AspNetUserClaims表中。如果您为该用户更新了表中任何声明的关联实体,那么IProfileService将发布这些更新的声明,因为您依赖userManager来获取您的声明。

基本上,为了找出属于用户的声明,您可以看到有一个名为AspNetUsers的"根表"。该表有一个关联的声明表AspNetUserClaims。这个表只是映射了用户和他们的1-M声明。简而言之,在该表中编辑索赔值是您需要做的。

请随意在GetProfileDataAsyncIProfileService中添加更多声明。基于表实体本身进一步添加声明是很常见的。正如您在更新#2

中所演示的那样

@Lutando用他的评论给我指明了正确的方向。

回答我自己的问题,用户管理器不是从user表中抓取声明,而是从另一个名为UserClaims的Identity表中抓取声明。我不知道这个表正在被使用,但现在它是有意义的。

正如Lutando所建议的,这个变通方法是完全有效的,我不需要依赖Identity的用户管理器来生成声明。我甚至不需要使用这个UserClaims表,因为我有名字和姓氏作为我的User表的一部分,如更新1所示。

相关内容

  • 没有找到相关文章

最新更新