通过 SSL 使用 .net core TestHost/TestServer 调用第三方容器:使用 Testservers CreateClient() 方法绕过 SSL 验证

Posted

技术标签:

【中文标题】通过 SSL 使用 .net core TestHost/TestServer 调用第三方容器:使用 Testservers CreateClient() 方法绕过 SSL 验证【英文标题】:Calling thirdparty container with .net core TestHost/TestServer via SSL: Bypass SSL Validation using Testservers CreateClient() method 【发布时间】:2021-05-09 18:27:31 【问题描述】:

我正在尝试使用 dotnet-testcontainers 库将 keycloak 作为测试容器添加到我的 .net 核心 (5) 集成测试中。

我的问题是,我正在为 HTTPS 支持而苦苦挣扎,因为我的集成测试使用了一个使用自签名证书和 TestServer-Class 的容器。

确切地说,我正在使用 Microsoft 的 TestServer 类来创建具有内存配置的真实 API 请求,以使用具有公开端口 8443 及其自签名证书的 keycloak-testcontainer。

问题是:我无法将HttpClientHandler 添加到TestServers HttpClient(通过serverCreateClient() 创建)以允许此处理程序中的不受信任的证书。我在分支 apitests-https 上创建了一个具体示例 here。失败的测试可以在here 中找到,它在SucceedsWhenGetRequestWithTokenReturnsListOfArticlestest 方法中。我在课程和 DemoApi 的 Startup.cs 中添加了一些评论 - 项目展示了我尝试过的内容。

因此,TestServers 内部 Jwt 中间件使用默认的 HttpClient 并抛出以下 AuthenticationException:

 ---> System.IO.IOException: IDX20804: Unable to retrieve document from: 'System.String'.
 ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
 ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch, RemoteCertificateChainErrors
   at System.Net.Security.SslStream.SendAuthResetSignal(ProtocolToken message, ExceptionDispatchInfo exception)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---

我已经尝试了多种方法来使其工作,并在代码中进行了注释。

DemoApi/Startup.cs: 尝试使用以下代码添加我自己的“测试”环境:

ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls |安全协议类型.Tls11 |安全协议类型.Tls12; ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

在 Api 测试中创建 TestServer-Instance 时通过 UseEnvironment("Testing") 使用它。调试显示代码被调用,但仍然出现异常。

DemoApiTestsApi/BaseFixture.csDemoApiTests/Infrastructure/Persistence/KeycloakTest.cs:请参阅此处了解我自己的 HttpClient 的工作实现,它带有处理程序以获取一般的令牌(这在分支中有效)-GetTestToken 是 BaseFixture 中的方法。

所以,老实说,我对如何使用 TestServer 或其他方式进行这项工作有些想法。本质上,我需要在BaseFixture.GetTestToken()/KeycloakTest.cs 中使用的处理程序也可以在我的TestServer 实例中使用,但不能在不接受参数的CreateClient() 中应用它。非常感谢任何帮助,可能是解决方案或提示以另一种方式解决此问题。当有另一种解决方法时,TestServer 不一定是固定的。

【问题讨论】:

【参考方案1】:

好的,我解决了。恕我直言,这不是最好的解决方案,但只要我没有另一个,这应该可行。我所要做的就是:

    IWebHostEnvironment作为字段添加到Startup.cs并注入Startup()构造函数。

然后启动看起来像这样:

        private IWebHostEnvironment CurrentEnv  get; 

        public Startup(IWebHostEnvironment env, IConfiguration configuration)
        
            Configuration = configuration;
            CurrentEnv = env;
        

从这里开始,剩下的就很简单了。在我的ConfigureServices() 方法中,我现在可以通过CurrentEnv.IsEnvironment("Testing") 检查我是否正在进行集成测试,对于这些我可以通过手动设置 jwt BackChannelHandler 来绕过 ssl 验证。

代码:

services.ConfigureJwtAuthentication(options =>
            
                options.Audience = Configuration["Jwt:Audience"];
                options.Authority = Configuration["Jwt:Issuer"];
                options.TokenValidationParameters.ValidIssuer = options.Authority;

                if (CurrentEnv.IsEnvironment("Testing"))
                
                    options.BackchannelHttpHandler = new HttpClientHandler()
                    
                        ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
                    ;
                
            );

我不得不承认,这感觉很老套,而且我最多也希望不需要接触任何与应用程序相关的代码来进行测试。最好的解决方案是从我的 keycloak 测试容器中获取证书并将其自动添加到 TestServers 应用程序实例的受信任证书中。如果有人可以就如何处理这个问题给出另一个答案/提示,我会很高兴看到它。但就目前而言,这是最有效的方法。

【讨论】:

以上是关于通过 SSL 使用 .net core TestHost/TestServer 调用第三方容器:使用 Testservers CreateClient() 方法绕过 SSL 验证的主要内容,如果未能解决你的问题,请参考以下文章

asp.net core 2.0 中的 WCF - 无法为具有权限的 SSL/TLS 安全通道建立信任关系

如何使用自托管 ASP.NET Core 2 应用程序 (httpsys) 进行 HTTPS (SSL)

C# .NET Core 3.1 无法建立 SSL 连接

在 c# (.net core) 中使用 httpclient 时无法建立 SSL 连接,但在 Postman 和 Browser 中有效

ssl 中客户端 Hello 数据包中 mshkg000019.blob.core.windows.net 的含义

C# .NET Core websocket ssl 问题 - dh 密钥太小