TestServer и HttpClient получают BadRequest для токена защиты от подделки в .net core web api - PullRequest
1 голос
/ 11 марта 2019

У меня проблема с вызовом конечной точки по умолчанию «/ api / values» из тестового проекта xUnit. Web API является основным проектом по умолчанию .net. Я всегда получаю плохой запрос - 400, даже я добавляю заголовок со значением из файла cookie AF на каждый запрос.

Сначала я настроил защиту от подделки в классе Startup.

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(
             opt =>
             {
                 opt.Filters.Add(new ValidateAntiForgeryTokenAttribute());
             }
            ).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        services.AddAntiforgery(options =>
        {
            options.HeaderName = "X-XSRF-TOKEN";
        });
    }

Затем добавьте отдельный контроллер и действие для создания файла cookie AF

    [IgnoreAntiforgeryToken]
    [AllowAnonymous]
    [HttpGet("antiforgery")]  
    public IActionResult GenerateAntiForgeryTokens()
    {
        //generate the tokens/cookie values
        //it modifies the response so that the Set-Cookie statement is added to it (that’s why it needs HttpContext as an argument).
        var tokens = _antiForgery.GetAndStoreTokens(HttpContext);
        Response.Cookies.Append("XSRF-REQUEST-TOKEN", tokens.RequestToken, new CookieOptions
        {
            HttpOnly = false,

        });

        return NoContent();
    }

Тогда я настраиваю тестовый класс

 public UnitTest1()
    {
        _server = new TestServer(
          WebHost.CreateDefaultBuilder()
           .ConfigureAppConfiguration((builderContext, config) =>
           {
               config.AddJsonFile("appsettings.test.json", optional: false, reloadOnChange: true);
           })
          .UseStartup<Startup>()
          .UseEnvironment("Development")
          );
        _client = _server.CreateClient();
        _client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
    }

и добавить метод в тестовый класс, чтобы получить значение из файла cookie AF для заголовка AF

  protected async Task<string> EnsureAntiforgeryToken()
    {
        string _antiforgeryToken = string.Empty;

            var response = await _client.GetAsync("/api/AntiForgery/antiforgery");
            response.EnsureSuccessStatusCode();
            if (response.Headers.TryGetValues("Set-Cookie", out IEnumerable<string> values))
            {
                var _antiforgeryCookie = Microsoft.Net.Http.Headers.SetCookieHeaderValue.ParseList(values.ToList()).SingleOrDefault(c => c.Name.StartsWith(XSRF_TOKEN, StringComparison.InvariantCultureIgnoreCase));
                _antiforgeryToken = _antiforgeryCookie.Value.ToString();
            }

        return await Task.FromResult<string>(_antiforgeryToken);
    }

и в моем тестовом методе я пытаюсь вызвать конечную точку

[Fact]
    public async Task Test1Async()
    {
        _antiforgeryCookie = await EnsureAntiforgeryToken();
        _client.DefaultRequestHeaders.Add("X-XSRF-TOKEN", _antiforgeryCookie);
        var result = await _client.GetAsync("/api/values"); //always get error 400
        Assert.True(true, "");
    }
...