ASP.NET Core WebAPI: проверка предоставленного токена защиты от подделки завершилась неудачно. Токен cookie и токен запроса были заменены

В моем приложении ASP.NET Core 2 WebAPI я хочу использовать AntiforgeryToken для моих методов контроллера POST, PUT и DELETE. С учетом этой документации я настроил ConfigureServices а также Configure методы моего Startup учебный класс. На стороне клиента я использую Angular 5 и их конфигурацию по умолчанию для Antiforgery. Я не могу понять, где проблема.

Вот выдержка из моего Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddAntiforgery(options =>
    {
        options.Cookie.Name = "XSRF-TOKEN";
        options.HeaderName = "X-XSRF-TOKEN";
        options.FormFieldName = "F-XSFR-TOKEN";
    });
    // ...
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider provider, ILogger<Startup> logger, IAntiforgery antiforgery)
{
    // ...
    app.Use(async (context, next) =>
    {
        var tokens = antiforgery.GetAndStoreTokens(context);
        context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
        await next();
    });
    // ...
}

Все мои контроллеры такие:

[Authorize]
[Route("api")]
public class CarController : Controller
{
    #region Variables
    private readonly DataContext _db;
    private ILogger<CarController> _logger;
    #endregion

    #region Constructor
    public CarController(DataContext db, ILogger<CarController> logger)
    {
        _db = db;
        _logger = logger;
    }
    #endregion

    #region Methods
    [AllowAnonymous]
    [HttpGet("[controller]")]
    public IActionResult Get()
    {
        try
        {
            return Ok(_db.Cars);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.GetHashCode(), ex, ex.Message);
            return BadRequest(ex);
        }
    }

    [HttpPost("[controller]")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Post([FromBody] CreateCar model)
    {
        try
        {
            // Creates a new car.
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.HResult, ex, ex.Message);
            return StatusCode(500, ex);
        }
    }

    [HttpPut("[controller]/{id}")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Put(int id, [FromBody] UpdateCar model)
    {
        try
        {
            // Updates a car
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.HResult, ex, ex.Message);
            return StatusCode(500, ex);
        }
    }
    #endregion
}

1 ответ

Я столкнулся с той же проблемой, и я думаю, что нашел проблему.

TLDR: options.Cookie.Name = "ASP-XSRF-TOKEN";

options.Cookie.Name в AddAntiforgery должен отличаться от файла cookie, который вы установили вручную context.Response.Cookies.Append,

Попробуйте изменить имя одного из них, и оно будет работать. Прямо сейчас вы переопределяете сгенерированный файл cookie, который использует options.Cookie.Name имя с tokens.RequestToken значение.

Вы можете заметить разницу в инструментах разработчика.

  • Маркер по умолчанию, созданный с использованием options.Cookie.Name помечен как http only (HttpOnly = true)
  • Прикрепленный вручную токен с помощью context.Response.Cookies.Append помечен как HttpOnly = false

Второй читается из JS/Angular (вы можете прочитать его в JS, потому что HttpOnly=false и отправляется в качестве заголовка в ваших запросах ajax и проверяется на соответствие стандартному, который не может быть прочитан из JS)

Другие вопросы по тегам