【问题标题】:JWT-based Authorization for API in .NET Core 2: No Unauthorized Error.NET Core 2 中基于 JWT 的 API 授权:没有未经授权的错误
【发布时间】:2019-08-05 21:06:20
【问题描述】:

好吧,我正在尝试在我的 .NET Core 2.x API 中建立基于 JWT 的授权。我一切正常,除此之外:我为应用授权而设置的测试操作不会拒绝未经身份验证的请求——它只是提供内容,就好像根本没有应用授权一样。

在我的Startup 我有:

    services.AddAuthentication(authOptions =>
    {
        authOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        authOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(jwtOptions =>
    {
        jwtOptions.Authority = configuration["Jwt:Issuer"];
        jwtOptions.SaveToken = true;
        jwtOptions.RequireHttpsMetadata = false;
        jwtOptions.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidIssuer = configuration["Jwt:Issuer"],
            ValidAudience = configuration["Jwt:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"]))
        };
    });

    services.AddAuthorization(options =>
    {
        options.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
            .RequireAuthenticatedUser()
            .Build());
    });

然后在Configure:

app.UseAuthentication();

我有一个像这样的登录 API 操作:

...
    [Route("api/user")]
    [ApiController]
    public class AppUserController : ControllerBase
    {
...
        [HttpPost("authenticate")]
        [AllowAnonymous]
        [Produces("application/json")]
        public async Task<IActionResult> Authenticate([FromBody] LoginDto model)
        {
            if (ModelState.IsValid)
            {
                var user = await _authenticationHandler.Authenticate(model);

                if (user != null)
                {
                    return Ok(_authenticationHandler.GetJwt(user.Name));
                }
            }

            ModelState.AddModelError("", "Invalid login attempt");

            return Ok();
        }
    }
...

其中 _authenticationHandler 是以下实例:

public class IdentityHandler
{
    private readonly UserManager<AppUser> _userManager;
    private readonly IConfiguration _configuration;

    public IdentityHandler
    (
        IConfiguration configuration,
        UserManager<AppUser> userManager
    )
    {
        _configuration = configuration;
        _userManager = userManager;
    }

    public string GetJwt(string username)
    {
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var claims = new HashSet<Claim>
        {
            new Claim(JwtRegisteredClaimNames.Sub, username),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString())
        };

        var token = new JwtSecurityToken
        (
            _configuration["Jwt:Issuer"], 
            claims: claims,
            signingCredentials: credentials,
            expires: DateTime.Now.AddDays(10)
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    public async Task<ClaimsIdentity> Authenticate(LoginDto loginModel)
    {
        var user = await _userManager.FindByNameAsync(loginModel.Username);
        var identity = new ClaimsIdentity();

        if (user != null && await _userManager.CheckPasswordAsync(user, loginModel.Password))
        {
            identity.AddClaim(new Claim(ClaimTypes.Name, user.NormalizedUserName));
        }

        return identity;
    }
}

最后,我有一个使用 Authorize 指令注释的 API 操作,例如:

[HttpGet("test")]
[Authorize]
[Produces("application/json")]
public IActionResult Test()
{
    return Ok("accepted");
}

我的期望是,如果我尝试导航到该操作,则该请求应被视为未经授权而被拒绝。它不是。作为 JWT 的新手,我不知道自己错过了什么。

我可以确认我的登录方法确实有效,找到用户并发出一个令牌,该令牌在客户端收到。

【问题讨论】:

  • 你能检查你的请求头,你有什么键和值吗?并在 Test 操作中添加断点并检查 User.Identity 的值是什么
  • 是的,我已经做到了。用户的测试操作中的传入值为 null - 即,根本没有特定身份,就像测试这种情况一样。

标签: c# .net-core jwt asp.net-authorization


【解决方案1】:

好吧,我找到了我自己问题的答案,经过一些额外的探索......在 Startup 类的 ConfigureServices 方法中,有必要指定要添加到 MVC 的授权过滤器,如下所示:

    services.AddMvc(config =>
        config.Filters.Add(new AuthorizeFilter(JwtBearerDefaults.AuthenticationScheme))
    );

就是这样。我对 [Authorize] 注释的操作现在按预期拒绝匿名请求。

【讨论】:

    猜你喜欢
    • 2020-02-11
    • 2019-03-20
    • 1970-01-01
    • 2019-01-04
    • 2018-12-26
    • 2018-08-05
    • 2020-03-28
    • 1970-01-01
    • 2020-03-04
    相关资源
    最近更新 更多