【问题标题】:How AspNet Identity generates user claimsAspNet Identity 如何生成用户声明
【发布时间】:2016-10-19 22:21:42
【问题描述】:

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

在身份服务器上,我还将身份与 EntityFramework 一起使用,以便我可以检索用户及其个人资料以生成声明等。

我面临一个奇怪的情况,例如我正在为用户更新FirstName,它会在数据库中正确更新,但是在生成用户级别声明时(given_namefamily_namename 和 @ 987654325@) 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: 这是用户模型。

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: 有一个明显的解决方法,即手动添加来自用户属性的声明,而不是依赖于身份的 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;
    }

【问题讨论】:

  • 你能粘贴你的应用程序用户数据模型吗?
  • @Lutando 在 Update 1 上粘贴的用户模型 FirstName 和 LastName 似乎不是 IdentityUser 的一部分,所以我添加了自己的属性。您是否认为 Identity 无法访问这些属性的值?为用户发出的声明具有旧名称和姓氏,不确定这些值将存储在哪里。
  • 还添加了带有解决方法的更新 2
  • 我假设您实际上并没有将这些作为声明存储在数据库中,这就是我要求用户数据模型的原因。此外,该解决方法非常好,并且是一种常见做法。您不限于仅签发存储为索赔的索赔。您发布的令牌并不关心您如何在持久层上存储或排列它们。

标签: asp.net-identity claims-based-identity claims identityserver4


【解决方案1】:

您需要告诉IProfileService 从哪里获取声明。

基本上来自AspNetCore.IdentityuserManager 只会获得该用户的相关声明。即IdentityUser.ClaimsAspNetUserClaims 表中仍然存在“旧值”。如果您针对表中的任何声明更新该用户的关联实体,那么 IProfileService 将发出这些更新的声明,因为您依赖 userManager 来获取您的声明。

基本上要找出属于用户的声明,您可以看到有一个名为AspNetUsers 的“根表”。该表有一个关联的声明,称为表AspNetUserClaims。此表仅映射用户及其 1-M 声明。简而言之,您需要在该表中编辑声明值。

请随时在IProfileService 中添加更多声明GetProfileDataAsync。基于表实体本身进一步添加声明是很常见的。正如您在更新 #2 中所展示的那样

【讨论】:

    【解决方案2】:

    @Lutando 用他的 cmets 为我指明了正确的方向。

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

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

    【讨论】:

      猜你喜欢
      • 2016-02-28
      • 1970-01-01
      • 2019-04-22
      • 1970-01-01
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-18
      相关资源
      最近更新 更多