【发布时间】:2021-12-04 22:03:36
【问题描述】:
我有一个使用 Grpc 的 .NET 5 WebApi 和一个在 YARP 反向代理后面运行的 IdentityServer4。反向代理正在使用有效的 Let's Encrypt 证书,并将请求路由到正在侦听 localhost:port 并使用自签名证书的另外两个。它们在 Linux Mint 20.1 上运行,我使用 OpenSSL 创建了自签名证书并将其添加到 /usr/local/share/ca-certificates/extra 并运行 update-ca-certificates 以更新证书存储。
一切运行良好,YARP 识别用于路由请求的 sefl 签名证书,但向需要授权的 WebApi 的请求抛出此异常:
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HMCHFQCVF5UE", Request id "0HMCHFQCVF5UE:0000000B": An unhandled exception was thrown by the application.
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'.
---> 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 because of errors in the certificate chain: NotTimeValid
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 ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
--- End of inner exception stack trace ---
at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
--- End of inner exception stack trace ---
at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Grpc.AspNetCore.Web.Internal.GrpcWebMiddleware.HandleGrpcWebRequest(HttpContext httpContext, ServerGrpcWebMode mode)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
我正在使用 Microsoft.AspNetCore.Authentication.JwtBear 5.0.11,这似乎就是它的来源。该错误似乎表明证书上的时间有问题,但使用 OpenSSL 检查非早于和非晚于日期都可以。 这是它在启动时的设置方式:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = appSettings.Authorization.Authority;
options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
options.TokenValidationParameters.ValidateAudience = false;
});
我尝试同时使用"https://localhost:port" 和"https://real.hostname" 作为权威,结果是一样的。我也尝试过使用options.RequireHttpsMetadata = false;,但它没有效果,我也不想切换到普通的http。
我还尝试使用相同的证书在我的 Windows 机器上运行相同的设置,并且在那里一切正常。什么可能导致不同的行为,我如何才能获得有关它实际尝试验证的证书以及它如何确定错误的更多信息?
【问题讨论】:
-
我在 github github.com/dotnet/runtime/issues/29409 上发现了这个问题,这似乎与您所拥有的类似,即使用 OpenSSL 制作的有效自签名证书上的证书过期。如问题中所述,您可以尝试在 OpenSSL 中将 keyUsage 设置为 keyCertSign。希望对您有所帮助。