Авторизация на основе JWT для API в .NET Core 2: неавторизованной ошибки - PullRequest
0 голосов
/ 14 марта 2019

Что ж, я пытаюсь остановить авторизацию на основе JWT в моем .NET Core 2.x API.У меня все работает, за исключением этого: Тестовое действие, которое я настроил для применения авторизации, не отклоняет неаутентифицированные запросы - оно просто обслуживает контент, как будто авторизация вообще не применяется.

В моем 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;
    }
}

Наконец, у меня есть действие API, аннотированное директивой Authorize, например:

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

И мойожидается, что если я попытаюсь перейти к этому действию, запрос будет отклонен как несанкционированный.Это не.Как новичок в JWT, я понятия не имею, что я пропустил.

Я могу подтвердить, что мой метод входа в систему действительно работает, поиск пользователя и выдача токена, который получен обратно на клиенте.

1 Ответ

0 голосов
/ 15 марта 2019

Ну, я нашел ответ на свой вопрос после некоторого дополнительного разбора ... в методе ConfigureServices класса Startup необходимо указать фильтр авторизации, который будет добавлен в MVC, например:

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

Вот и все. Мое действие с аннотацией [Authorize] теперь отклоняет анонимные запросы, как и ожидалось.

...