本地登录后 User.Identity.Name 为空

Gha*_*sen 7 asp.net-identity identityserver4 .net-core-3.0

我配置IdentityServer4为使用 AspNet Identity (.net core 3.0) 以允许用户进行身份验证(登录名/密码)。

我的第三个应用程序是.net core 3.0.

登录后,身份验证和授权成功,但我无法通过 User.Identity.Name 检索 UserId,它为空/空。

但是,我可以看到包含sub包含 userId的声明的声明信息。

这是我用于 IdentityServer4 Web 应用程序的包

PackageReference Include="IdentityServer4" Version="3.0.1" />
Run Code Online (Sandbox Code Playgroud)

Nic*_*une 5

我面临同样的问题,我找到了两个解决方案。

  • [方案一] - WebApi - 更新 IdentityServerAuthentication 配置的 NameClaimType

在 WebApi 的启动文件中,更新 NameClaimType 属性

services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
        .AddIdentityServerAuthentication(options =>
         {
               options.CacheDuration = xxxxx;
               options.Authority = xxxxx;
               options.ApiName = xxxx;
               options.ApiSecret = xxxxx;
               options.RequireHttpsMetadata = xxxxxx;
               options.NameClaimType = JwtClaimTypes.Subject;
         });
Run Code Online (Sandbox Code Playgroud)
  • [解决方案 2] - IdentityServer4 App - 创建新配置文件以自定义您的声明

为 IdentityServer4 服务器创建一个新的配置文件,以便自定义令牌内的声明。

public class AspNetIdentityProfileService : IProfileService
{
    private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
    private readonly UserManager<ApplicationUser> _userManager;

    public AspNetIdentityProfileService(UserManager<ApplicationUser> userManager, IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory)
    {
        _userManager = userManager;
        _claimsFactory = claimsFactory;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var sub = context.Subject.GetSubjectId();
        var user = await _userManager.FindByIdAsync(sub);
        var principal = await _claimsFactory.CreateAsync(user);

        var claims = principal.Claims.ToList();

        claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();

        claims.Add(new Claim("name", user.UserName));
        context.IssuedClaims = claims;
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        var sub = context.Subject.GetSubjectId();
        var user = await _userManager.FindByIdAsync(sub);

        context.IsActive = user != null;
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的启动文件中

services.AddTransient<IProfileService, AspNetIdentityProfileService>();
Run Code Online (Sandbox Code Playgroud)

  • 那是因为 IdentityServer 的 oidc 实现不是这样工作的。默认情况下,_访问令牌_中没有身份声明,并且_身份令牌_仅包含子声明。要获取其他信息,_client_ 必须访问 UserInfo 端点(使用访问令牌)来请求用户信息,例如姓名。Api 实际上无法访问此信息,为什么要访问呢?没有 UI 显示名称。如果需要将其作为请求的一部分,则应将其添加到请求的内容中。 (2认同)