【问题标题】:UseJwtBearerAuthentication does not get User.Identity.Name populatedUseJwtBearerAuthentication 没有填充 User.Identity.Name
【发布时间】:2017-06-09 09:53:08
【问题描述】:

我正在尝试在ASP.NET Core Web API 项目中使用JWT 进行身份验证机制。假设这个项目没有MVC 部分并且不使用cookie 认证。我基于this guide 创建了我的代码。

登录效果很好,使用[Authorize] 属性进行保护也可以,但User.Identity.Namenull。我该如何解决这个问题?

我的代码:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
    var tokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],

        ValidateAudience = true,
        ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],

        ValidateIssuerSigningKey = true,
        IssuerSigningKey = _signingKey,

        RequireExpirationTime = true,
        ValidateLifetime = true,

        ClockSkew = TimeSpan.Zero
    };

    app.UseJwtBearerAuthentication(new JwtBearerOptions
    {
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        TokenValidationParameters = tokenValidationParameters,
        AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme
    });

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

    [HttpPost]
    [AllowAnonymous]
    [Route("Login")]
    public async Task<IActionResult> Login([FromForm] ApplicationUser applicationUser)
    {
        //assume user/pass are checked and are ok

        _logger.LogInformation(1, "API User logged in.");
        var user = await _userManager.FindByNameAsync(applicationUser.UserName);
        var roles = await _userManager.GetRolesAsync(user);

        var claims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.Sub, applicationUser.UserName),
            new Claim(ClaimTypes.NameIdentifier, applicationUser.UserName),
            new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
            new Claim(JwtRegisteredClaimNames.Iat,
                    ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(),
                    ClaimValueTypes.Integer64),
                    new Claim("Claim", "Value")
        };

        if (roles != null)
            foreach (var role in roles)
                claims.Add(new Claim("role", role));

        // Create the JWT security token and encode it.
        var jwt = new JwtSecurityToken(
            issuer: _jwtOptions.Issuer,
            audience: _jwtOptions.Audience,
            claims: claims,
            notBefore: _jwtOptions.NotBefore,
            expires: _jwtOptions.Expiration,
            signingCredentials: _jwtOptions.SigningCredentials);

        var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

        // Serialize and return the response
        var response = new
        {
            access_token = encodedJwt,
            expires_in = (int)_jwtOptions.ValidFor.TotalSeconds
        };

        var json = JsonConvert.SerializeObject(response, _serializerSettings);
        return new OkObjectResult(json);
    }

【问题讨论】:

    标签: authentication asp.net-web-api asp.net-core jwt


    【解决方案1】:

    app.UseAuthentication(); 添加到

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 
    

    解决了我的问题。

    【讨论】:

      【解决方案2】:

      另一个选项是在tokenValidationParameters 中为JwtRegisteredClaimNames.Sub 设置命名空间。这将让您继续使用标准:

      var tokenValidationParameters = new TokenValidationParameters
      {
          // Ensure that User.Identity.Name is set correctly after login
          NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
      
          ... existing code ...
      }
      

      更新:Diogo Barros 在我的博客上就这个话题发表了评论:

      “你好,

      感谢您的帮助。这对我有用。 为了更加一致和安全,您可以使用 ClaimTypes.NameIdentifier(在 System.Security.Claims 命名空间中),而不是硬编码字符串。"

      我已将代码更改为使用内置 ClaimTypes 枚举,因为它比使用命名空间字符串更优雅。

      【讨论】:

      • 使用令牌的“子”字段看起来比接受的答案更标准,并且还减少了一点令牌大小:-)
      【解决方案3】:

      在您的声明中(第二个代码 sn-p)我只能看到这个:

      new Claim(ClaimTypes.NameIdentifier, applicationUser.UserName),
      

      但你需要添加这个:

      new Claim(ClaimTypes.Name, applicationUser.UserName),
      

      那么 User.Identity.Name 应该包含用户名。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-06
        • 2016-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多