【问题标题】:User.Identity.Name is always null when using AspNetIdentity with IdentityServer3将 AspNetIdentity 与 IdentityServer3 一起使用时,User.Identity.Name 始终为空
【发布时间】:2017-07-15 11:17:20
【问题描述】:

几天来,我一直在尝试使用 AspNetIdentity 设置新的 IdentityServer3。我可以使用现有的身份数据库登录,这一切都很好,但我永远无法让 User.Identity.Name 包含数据。 我已尝试多次尝试添加自定义声明和范围以及向客户端添加范围。

最后,我加载了 IdentityServer3 示例存储库并使用 webforms 客户端项目对其进行了测试,因为它已经在其“关于”页面中使用了 User.Identity.Name。

使用 WebForms 示例客户端 + AspNetIdentity 示例服务器 = User.Identity.Name 始终为空 使用 WebForms 示例客户端 + SelfHost 和 Seq 示例服务器 = User.Identity.Name 和数据 我已经尝试过其他示例宿主项目,它们都可以很好地填充 User.Identity.Name 值。

现在,在客户端,我编写了一个解决方法来提取“preferred_username”声明值并使用它设置“名称”声明。

var id = new claimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);

//set the User.Identity.Name value
var name = id.Claims.Where(x => x.Type == "name").Select(x => x.Value).FirstOrDefault() ??
           id.Claims.Where(x => x.Type == "preferred_username").Select(x => x.Value).FirstOrDefault();
id.AddClaim(new Claim("name", name));

我的问题是:

  1. 为什么 AspNetIdentity 包默认不填充这个?
  2. 我需要在服务器端进行哪些更改,以便无需更改客户端?

【问题讨论】:

  • 你有没有找到解决这个问题的“更好”的解决方案?
  • 我们将保留该解决方案。有用。我们当时还添加了其他自定义声明。我们没有足够的时间深入研究我发布的示例之间的差异。
  • @TheBrian 变量userInfoResponse如何在上述解决方法中获得它的值?

标签: asp.net asp.net-identity identityserver3


【解决方案1】:
public static IEnumerable<ApiResource> GetApis()
{
   return new ApiResource[]
   {
      new ApiResource("MyApi", "My Admin API")
      {
          UserClaims =  { JwtClaimTypes.Name, JwtClaimTypes.Email }
      }
   };
}

在 Identityserver4 中,您可以将 UserClaims 添加到您的资源中。帮我修好了。

【讨论】:

    【解决方案2】:

    在 IdentityServer4 上,您可以在服务器上实现 IProfileService 并在 GetProfileDataAsync 中添加声明

    public class AspNetIdentityProfileService : IProfileService
    {
        protected UserManager<ApplicationUser> _userManager;
    
        public AspNetIdentityProfileService(UserManager<ApplicationUser> userManager)
        {
            _userManager = userManager;
        }
    
        public Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            //Processing
            var user = _userManager.GetUserAsync(context.Subject).Result;
    
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, user.UserName),
            };
    
            context.IssuedClaims.AddRange(claims);
    
            //Return
            return Task.FromResult(0);
        }
    
        public Task IsActiveAsync(IsActiveContext context)
        {
            //Processing
            var user = _userManager.GetUserAsync(context.Subject).Result;
    
            context.IsActive = (user != null) && ((!user.LockoutEnd.HasValue) || (user.LockoutEnd.Value <= DateTime.Now));
    
            //Return
            return Task.FromResult(0);
        }
    }
    

    然后将“AddProfileService()”添加到您的 ConfigureServices 方法中。

    services.AddIdentityServer(...)
        ...
        .AddProfileService<AspNetIdentityProfileService>();
    

    【讨论】:

    • 该解决方案的问题是您从 IdpUsers 获取用户名,这与 ProviderKey 没有必要相同 - 在 SSO 环境中,您可能希望同时返回提供程序密钥和 SID客户。
    猜你喜欢
    • 2019-12-11
    • 1970-01-01
    • 2015-03-22
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 2015-11-28
    相关资源
    最近更新 更多