C# Connect to Ravendb 一直失败并显示错误:此服务器需要客户端证书进行身份验证,但客户端未提供任何证书

问题描述

不管我尝试什么,在一个新的 .net 5 API 项目中,我无法连接到 RavenDB。它给了我一个错误:

此服务器需要客户端证书进行身份验证,但不需要 由客户提供。

我连接数据库的方式:

byte[] certificateBytes = _certificateProvider.GetCertificate("CERT-NAME").Result;
string passphrase = _secretProvider.GetSecret("CERT-PASSPHRASE").Result;
X509Certificate2 certificate = new X509Certificate2(certificateBytes,passphrase);

var documentStore = new DocumentStore()
{
    Urls = new[] { databaseOptions.DbUrl },Conventions =
    {
        UseOptimisticConcurrency = true,FindCollectionName = findCollectionName
    },Database = "DBNAME",Certificate = certificate,}.Initialize();

证书提供者和机密提供者从 Azure Key Vault 中获取数据。我验证了 X509Certificate,它的指纹与我在 RavenDB 的管理面板中获得的指纹相同。这样就正确加载了。此外,证书对请求的数据库具有读/写权限

但是当我执行以下操作时:

using (IAsyncDocumentSession session = documentStore.OpenAsyncSession())
{
    var entity = await session.Query<EntityDTO>()
        .SingleOrDefaultAsync();
}

然后我收到以下错误:

此服务器需要客户端证书进行身份验证,但不需要 由客户提供。

这是在初始化文档存储时给出的证书。任何人都知道如何继续这样做,因为 RavenCloud 没有提供更多信息?

在另一个项目(.net core 3.1)中,具有相同证书的相同代码有效。但是在 .net 5 的发行说明中找不到任何可能导致这种情况的内容。

解决方法

您需要加载带有 MachineKeySet 标志的证书。

X509Certificate2 certificate = new X509Certificate2(certificateBytes,passphrase,X509KeyStorageFlags.MachineKeySet);

这将解决 Azure 中的问题,但您的本地开发机器在此更改后可能会出现问题。您需要允许运行 RavenDB 的用户完全访问本地计算机上的 MachineKeySet 文件夹。

"C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys"

还请注意,如果之后不处理证书,私钥会堆积在该文件夹中(每次 X509Certificate2 构造函数打开证书时都会向该文件夹写入一个密钥)。

,

在 RavenDB 论坛中@iftah 回应说你应该将存储标志设置为 MachineKeySet,因为私钥。

虽然对我来说不是这样,但它给了我一个检查的方向。我正在使用 CertificateClient 和 GetCertificateAsync 从 Azure Key Vault 加载证书。这只会给你公钥。所以从来没有私钥。

借助这篇文章:KeyVault generated certificate with exportable private key。我发现我可以将 SecretClient 与 GetSecretAsync 一起使用。然后使用 Convert.FromBase64String() 并返回私钥。

对于那些有类似问题的人。请在加载证书时验证您是否拥有私钥。我的新代码:

byte[] certificateBytes = Convert.FromBase64String(_secretProvider.GetSecret("CERT-NAME").Result);
X509Certificate2 certificate = new X509Certificate2(certificateBytes,string.Empty);

var documentStore = new DocumentStore()
{
    Urls = new[] { databaseOptions.DbUrl },Conventions =
    {
        UseOptimisticConcurrency = true,FindCollectionName = findCollectionName
    },Database = "DBNAME",Certificate = certificate,}.Initialize();

如果你想让它在 Azure 上运行,请不要忘记以下面的方式加载你的证书,就像上面@iftah 建议的那样:

X509Certificate2 certificate = new X509Certificate2(certificateBytes,string.Empty,X509KeyStorageFlags.MachineKeySet);

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...