c#中带有HttpClient的客户端证书

Som*_*dam 6 c# client-certificates x509certificate2 dotnet-httpclient

想要将带有客户端证书(.p12 或 .pfx)的数据从 Windows 应用程序发送到服务器机器,在 .Net Framework 4.6 中开发的 Windows 应用程序,操作系统是 Windows 10。

当邮递员使用客户端证书(.p12 或 .pfx)[加载到设置选项卡 -> 添加客户端证书 -> 放置主机名,选择 pfx 文件,输入密码] 时,一切正常(客户端证书发送到服务器机器),但是从下面的 c# 代码发出,

X509Certificate2 certificate = new X509Certificate2(certificateFilePath, "password");
WebRequestHandler handler = new WebRequestHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateValidationCallback = (a, b, c, d) => { return true; };
handler.ClientCertificates.Add(certificate);


HttpClient request = new HttpClient(handler);
request.DefaultRequestHeaders.Add("User-Agent", UserAgent);
// added other headers and data
var result = request.PostAsync(url, byteContent).Result;
string resultContent = result.Content.ReadAsStringAsync().Result;
Run Code Online (Sandbox Code Playgroud)

还与 fiddler 交叉检查 Postman hit 和 c# hit。

当服务器未收到客户端证书时,返回 403 错误。

use*_*994 6

HttpStatus 代码 403 可能是由 TLS 问题引起的,因为未使用预期的服务器 TLS 版本调用 API。resultContent您可以从代码行检查结果string resultContent = result.Content.ReadAsStringAsync().Result;

要设置 SslProtocol,您可以在 Handler 中进行设置(如果您的目标是 .Net 4.7 或 .Net core)

WebRequestHandler handler = new WebRequestHandler();
handler.SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
Run Code Online (Sandbox Code Playgroud)

或在应用程序级别使用ServicePointManagerStartup 方法(或 4.7 之前的 .Net Framework 版本)

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Run Code Online (Sandbox Code Playgroud)

旁注建议 - 我建议您使用纯异步/等待模式。不要通过调用 来对 IO 请求使用同步调用.Result


wob*_*ntu 5

我假设您的处理程序无权访问用于身份验证的私钥。

这可能是由于您的示例中的第 1 行造成的,在该行中您使用默认密钥存储标志导入证书。当然这只是一个猜测,我没有你的证书来检查这个,但你可以通过调用来验证

// Sample for RSA, use DSA if required
var privateKeyParams = ((RSA)certificate.PrivateKey).ExportParameters(true);
Run Code Online (Sandbox Code Playgroud)

如果无法访问关键参数,这将导致 CryptographicException(“不支持”或类似)。

请尝试以下方法来加载证书:

X509Certificate2 certificate = new X509Certificate2(
  certificateFilePath, "password",
  X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet);
Run Code Online (Sandbox Code Playgroud)

只是进一步的旁注;如果您在生产代码中使用它,请确保扩展您的服务器证书验证回调(您的第 4 行)以实际验证服务器证书。请参阅X509Chain.Build,它还允许您根据需要修改验证选项(路径验证实际执行的操作可以在RFC5280 中读取)。