我们有一个Web应用程序,该应用程序必须使用双向SSL证书身份验证与HTTP服务进行通信。以下是相关代码
X509Certificate certificate = GetCertFromStore(StoreName.My, StoreLocation.LocalMachine, certName);
if (certificate != null)
{
Log.Debug($"Adding client cert {certificate.Subject}");
WebRequestHandler handler = new WebRequestHandler();
handler.ClientCertificates.Add(certificate);
handler.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.UseProxy = false;
using (var client = new HttpClient(handler))
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var postObj = new
{
// somestuff
};
var postBody = JsonConvert.SerializeObject(postObj);
var httpContent = new StringContent(postBody, Encoding.UTF8, "application/json");
HttpResponseMessage httpResponse = client.PostAsync(queryUrl, httpContent).Result;
if (httpResponse.IsSuccessStatusCode)
{
// codey code
}
else
{
Log.Error($"some error stuff.");
}
}
}
else
{
Log.Error($"Unable to find the certificate with name: {certName}");
}
目前,我们正在使用提供给第三方服务提供商的自签名证书,并从中安装相关的服务器证书。
在本地开发计算机上,所有工具都可以正常工作-建立连接,并正确进行服务调用和响应。
但是,当我们部署在Azure VM(我们的测试环境)上时,证书交换失败。查看Wireshark跟踪,我们可以看到服务器证书已被接受,但是它显示发送了0个客户端证书。我们知道(在日志记录中)由于在日志中找到了客户端证书,因此从Wireshark跟踪中可以看到,客户端证书名称确实列在服务器证书请求的“专有名称”中。
即使代码将期望的客户端证书添加到WebRequestHandler中,也无法弄清楚它在握手过程中消失了。
答案 0 :(得分:0)
我们解决了这个问题。
首先,我认为证书是在没有私钥的情况下安装的。在我们的函数GetCertFromStore中,它正在查找证书,但我认为,因为它没有私有密钥,因此没有发送它。 (发现证书的事实是我们感到困惑的-我们认为,如果找到证书,那么一切都很好。)
为解决此问题,我们从商店中将其删除,然后使用.pfx文件重新安装,并确保也导入私钥。
还有一个权限问题,我们在StackOverflow here上找到了答案(注意,不是标记为“ answer”的答案,而是关于权限的答案)。为了使Web应用程序能够加载和使用带有私钥的证书,应用程序池标识(或模拟用户)必须对已安装证书的密钥文件具有读取权限(通常在C:\ ProgramData \ Microsoft \ Crypto \ RSA中找到) \ MachineKeys)。