如何解决通过 SSL 使用 .net core TestHost/TestServer 调用第三方容器:使用 Testservers CreateClient() 方法绕过 SSL 验证
我正在尝试使用 dotnet-testcontainers 库将 keycloak 作为测试容器添加到我的 .net core (5) 集成测试中。
我的问题是,我在使用自签名证书和 TestServer-Class 进行集成测试的容器中遇到了 HTTPS 支持问题。
准确地说,我正在使用 Microsoft 的 TestServer 类来创建具有内存配置的真实 API 请求,以使用具有公开端口 8443 及其自签名证书的 keycloak-testcontainer。
问题是:我无法向 TestServers HttpClient(通过 HttpClientHandler
创建)添加 serverCreateClient()
以允许在此处理程序中使用不受信任的证书。我在分支 apitests-https 上创建了一个具体示例 here。可以在 here 中找到失败的测试,它在 SucceedsWhenGetRequestWithTokenReturnsListOfArticles
测试方法中。我在类和 DemoApi 的 Startup.cs 中添加了一些评论 - 显示我尝试过的项目。
因此,TestServers 内部 Jwt Middleware 使用默认的 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 | SecurityProtocolType.Tls12; ServicePointManager.ServerCertificateValidationCallback += (发件人,证书,链,sslPolicyErrors)=> true;
在 Api 测试中创建 TestServer-Instance 时通过 UseEnvironment("Testing")
使用它。调试显示代码被调用,但还是出现异常。
-
DemoApiTestsApi/BaseFixture.cs
或DemoApiTests/Infrastructure/Persistence/KeycloakTest.cs
:请参阅此处了解我自己的带有处理程序的 HttpClient 的工作实现,以获取一般的令牌(这在分支中有效) -GetTestToken
是中的方法基础夹具。
所以,老实说,我对如何使用 TestServer 或其他方式进行这项工作有点想法。本质上,我需要在 BaseFixture.GetTestToken()
/KeycloakTest.cs
中使用的处理程序也能在我的 TestServer 实例中使用,但不能在不接受参数的 CreateClient()
中应用它。任何帮助都受到高度赞赏,它可能是解决方案或解决此问题的另一种方法的提示。如果有其他方法可以解决这个问题,TestServer 不一定是固定的。
解决方法
好的,我解决了。恕我直言,这不是最好的解决方案,但只要我没有另一个解决方案,这应该可行。我所要做的就是:
- 将
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 testcontainer 获取证书并将其自动添加到 TestServers Application 实例的受信任证书中。如果有人可以就如何处理这个问题给出另一个答案/提示,我会很高兴看到它。但就目前而言,这是最有效的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。