首页 > 解决方案 > 在 Linux 中如何信任 dotnet 的开发证书?

问题描述

我正在学习关于在 .NET 中构建微服务的在线课程 - https://www.dotnetmicroservices.com/

但是,当讲师在 Windows 上运行时,我正在使用 Linux - Linux Mint 20.1 (Ulyssa)。

.NET core 和 .NET 5.0 应该是跨平台的,到目前为止,我在让事情正常工作方面没有真正的问题。

至此,我有两个webapi服务,一个提供身份服务,一个提供目录服务。

身份服务配置为使用 IdentityServer4、IdentityServer4.AspNetIdentity 和 Microsoft.AspNetCore.Identity.UI 来提供 OAuth 2.0 和 OpenID 服务。

目录服务配置为使用 Microsoft.AspNetCore.Authentication.JwtBearer,并且需要有效的 JWT 才能访问端点。

因此,在 Postman 中,我将请求配置为访问目录服务中的简单 GET 端点。在请求的授权选项卡中,我选择 OAuth 2.0,并输入发出请求所需的数据,包括 Auth URL 和访问令牌 URL(https://localhost:5003/connect/authorize 和 https://localhost:5003 /连接/令牌)。

当我单击 Postman 的“获取新访问令牌”按钮时,我进入登录页面,我登录,然后得到“管理访问令牌”对话框。我可以从对话框中复制访问令牌或 id_token 并将它们粘贴到https://jwt.ms/中,它们看起来都很好。

这么多是有效的。

但是当我点击 Postman 的“使用令牌”按钮,然后在请求上执行“发送”时,我在目录服务中得到一个异常:

fail: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[3]
      Exception occurred while processing message.
      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: PartialChain
         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()

看起来问题在于 dotnet 的开发人员证书不受信任。

执行此操作的常用方法是使用 dotnet cli:

dotnet dev-certs https --trust

但在 Linux 上,这会返回:

已请求信任 HTTPS 开发证书。不支持自动信任 Linux 发行版上的证书。有关如何手动信任 Linux 发行版上的证书的说明,请访问https://aka.ms/dev-certs-trust

所以我去了https://aka.ms/dev-certs-trust,它包含很多东西,其中大部分显然是不相关的。“Ubuntu 信任服务到服务通信的证书”部分似乎很恰当:

sudo dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
sudo update-ca-certificates

虽然运行没有问题,但它并没有解决问题。

至于其余部分,该页面显示“建立信任是特定于浏览器的。以下部分提供了 Chromium 浏览器 Edge 和 Chrome 以及 Firefox 的说明。”

而且我看不出两者与手头的问题有什么关系。

dotnet core 在验证证书时在做什么?我需要做什么才能将 dotnet 开发人员的证书标记为受信任?

标签: linuxasp.net-core.net-coreidentityserver4

解决方案


要么您必须停止使用 HTTPS,而是在服务之间使用 HTTP。

我假设您使用容器来托管服务?并且要使 HTTPS 正常工作,您需要一个域名并将该域名映射到与证书匹配的容器,并使用 localhost(开发证书)映射到容器,我觉得这是一个坏主意。

最好获得一个真正的证书,然后使用不同的技术映射到容器。就像编辑主机文件以将域映射到服务的 IP 地址一样。

在开发/生产中,我通常在 Azure Key Vault 中托管我的 HTTPS 证书,并在启动时将其下载并添加到 ASP.NET Core。

当我在本地工作时,我使用mkcert工具为域 indentityservice.local 创建了一个证书

mkcert.exe -install

mkcert -pkcs12 -p12-file identityservice.local.pfx identityservice.local

然后我复制生成的 identityservice.local.pfx 并将其添加到我的项目中。然后,如果一切正常,我可以使用https://identityService.local联系我的本地 IdentityServer

我也确实将此条目添加到我的本地主机文件中 C:\Windows\System32\drivers\etc

127.0.0.1 identityService.local

推荐阅读