【问题标题】:How to use (Microsoft.AspNetCore.TestHost)TestServer with Client Certificate如何将 (Microsoft.AspNetCore.TestHost)TestServer 与客户端证书一起使用
【发布时间】:2020-01-08 13:59:01
【问题描述】:

在 .net core api 中启用证书身份验证会导致 TestServer 在集成测试中始终返回 403-Forbidden(尽管请求中使用了证书)。

我尝试更改 TestClientProvider 中的 CertificateValidationService,但似乎证书验证在达到用户定义的身份验证逻辑之前失败。 在 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();
        });
    }
  1. 在您的 api 上使用“授权”属性
// WeatherForecastController.cs  (VS 2019 template)
    [ApiController]
    [Route("api/weather")]
    [Authorize]
    public class WeatherForecastController : ControllerBase
    {
    ...
    }
  1. 使用 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);
        }
    }

【问题讨论】:

    标签: c# ssl asp.net-core integration-testing asp.net-core-webapi


    【解决方案1】:

    根据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";
        });
    

    【讨论】:

    • 相同的解决方案,但不同的实现是设置 BaseAddressTestServer : testServer.BaseAddress = new Uri("https://localhost/"); // use HTTPS for all requests
    猜你喜欢
    • 1970-01-01
    • 2020-01-23
    • 2010-12-24
    • 2013-01-19
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多