Как использовать (Microsoft.AspNetCore.TestHost) TestServer с клиентским сертификатом - PullRequest
1 голос
/ 08 января 2020

Включение аутентификации сертификата в. net core api заставляет TestServer всегда возвращать 403-Forbidden в интеграционных тестах (несмотря на сертификат, использованный в запросе).

Я пытался изменить CertificateValidationService в TestClientProvider, но, похоже, сбой проверки сертификата до достижения пользовательского логина аутентификации c. Служба работает правильно с сертификатом клиента при развертывании в Azure.

Я что-то упустил? Есть ли способ использовать TestServer с API, защищенным сертификатом клиента?

Для воспроизведения

  1. Включить аутентификацию сертификата в. NET Core API https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth?view=aspnetcore-3.1
// Startup.cs
    ...
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<CertificateValidationService>();
        services.AddAuthentication(
            CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(options =>
        {
            ...
        });
        services.AddAuthorization();
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
    {
        ...

        app.UseRouting();

        app.UseCertificateForwarding();
        app.UseAuthentication();
        app.UseAuthorization();
        ...

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
Используйте атрибут "authorize" на вашем API
// WeatherForecastController.cs  (VS 2019 template)
    [ApiController]
    [Route("api/weather")]
    [Authorize]
    public class WeatherForecastController : ControllerBase
    {
    ...
    }
Написать интеграционный тест с использованием Microsoft.AspNetCore.TestHost
// IntegrationTests/ClientCertificateTests.cs
    [Fact]
    public async void GivenValidCertificate_PerformGet_ExpectSuccess()
    {
        X509Certificate2 validClientCertificate;
        using (var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
        {
            certStore.Open(OpenFlags.ReadOnly);
            validClientCertificate = certStore.Certificates.Find(X509FindType.FindByTimeValid, DateTime.Now, true)[0];
        }

        using (var server = new TestClientProvider(ignoreCertificate: false).Server)
        {
            // Act
            var result = await server.SendAsync(context =>
            {
                context.Connection.ClientCertificate = validClientCertificate;
                context.Request.Method = "GET";
                context.Request.Path = "/api/weather";
            });

            // Assert
            Assert.Equal(200, result.Response.StatusCode);
        }
    }

1 Ответ

1 голос
/ 10 января 2020

Согласно https://github.com/dotnet/aspnetcore/issues/18177, мне также пришлось установить схему запроса «https», которая работала для меня.

    var result = await server.SendAsync(context =>
    {
        context.Connection.ClientCertificate = validClientCertificate;
        context.Request.Method = "GET";
        context.Request.Scheme = "https";
        context.Request.Path = "/api/weather";
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...