【问题标题】:Client certificate with HttpClient in c#c#中带有HttpClient的客户端证书
【发布时间】:2020-02-03 20:09:33
【问题描述】:

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

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

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

【问题讨论】:

  • 错误是什么?
  • 错误类似于 403 Forbidden
  • 您的服务器知道客户端证书吗?它需要证书来最终验证它。 @Kahbazi,根据文档,WebRequestHandler 是 HttpClientHandler。
  • @SomnathKadam - 由于 TLS 协议,您可能会收到此错误代码。如果您的服务器应用程序配置了一个固定的 TLS 版本,而您的客户端没有,那么您应该使用提供的 TLS 版本(或所有类似 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;)发送请求。另外,您能否发布结果内容,它应该有错误详细信息。
  • 这种失败有很多可能的原因,其中一些相当模糊。我建议打开trace,这将允许您查看握手过程的每个步骤并准确确定出了什么问题。

标签: c# dotnet-httpclient client-certificates x509certificate2


【解决方案1】:

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

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

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

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

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

X509Certificate2 certificate = new X509Certificate2(
  certificateFilePath, "password",
  X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet);

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

【讨论】:

    【解决方案2】:

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

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

    WebRequestHandler handler = new WebRequestHandler();
    handler.SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
    

    或在应用程序级别使用 ServicePointManager 在 Startup 方法(或 4.7 之前的 .Net 框架版本)

    System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
    

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

    【讨论】:

    • 我已经设置了 System.Net.ServicePointManager.SecurityProtocol,但不能在 Windows 10 上使用框架 4.8。
    • 你能从代码行string resultContent = result.Content.ReadAsStringAsync().Result中得到resultContent的结果吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-21
    • 2011-12-10
    • 2013-02-25
    • 2023-03-23
    • 1970-01-01
    • 2019-10-25
    相关资源
    最近更新 更多