c# - UWP 应用程序 HttpClient HTTPS 客户端证书问题

标签 c# .net https uwp windowsiot

我正在用 C# 编写一个 UWP 应用程序,它最终用于物联网,但现在我只在本地调试。我正在使用 Windows.Web.Http.HttpClient 连接到一个自托管的 WCF REST Web 服务,我也编写了该服务并在同一台机器上作为控制台应用程序运行以进行测试。该服务需要使用证书进行相互身份验证,因此我有 CA 证书、服务证书和客户端证书。

我的 UWP 代码是这样工作的:

  1. 检查应用程序证书商店是否安装了客户端证书和 CA 证书。
  2. 如果没有,请分别从 PFX 文件和 CER 文件安装。
  3. Certificate 附加到 HttpBaseProtocolFilter 并将过滤器添加到 HttpClient
  4. 调用HttpClient.PostAsync

调用 PostAsync 后,出现以下错误:安全通道支持中发生错误。经过大量在线搜索后,根据常识,我很确定 HttpClient 是因为建立相互验证的 SSL 连接时出现问题而呕吐。但根据我的故障排除,我想不出为什么。

为了进一步排除故障,我使用 System.Net.Http.HttpClient 编写了一个普通的旧控制台应用程序,将客户端证书附加到请求中,一切正常。遗憾的是,UWP 不完全支持 System.Net。我还尝试过不将证书附加到 UWP HttpClient,应用会提示我使用 UI 选择已安装的证书。我选择了正确的证书,但仍然出现相同的异常(这至少让我知道证书已正确安装并从应用程序的角度正确地通过 CA 进行了验证)。此外,我从浏览器点击 Web 服务上的 GET,在出现提示时选择客户端证书,然后能够下载文件。

我已经尝试过使用 Fiddler,并且我认为由于它代理流量的方式,它似乎可以进一步工作,除了我的 Web 服务拒绝请求为禁止(大概是因为 Fiddler 不包括正确的客户端证书在请求中)。我还没有使用 Wireshark,因为在 Windows 上使用本地主机让 Wireshark 工作很痛苦。

我的下一步是开始将 Web 服务更改为不需要客户端身份验证,然后看看这是否是问题所在。

两个问题:为什么 Windows.Web.Http.HttClient 在这种情况下不起作用?而且,不太重要的是,有什么关于好的 HTTP 监控工具的建议可以帮助我进一步调试吗?

最佳答案

事实证明,这篇 MSDN 帖子提供了答案。似乎是对 MS 部分的疏忽,需要事先对 API 进行单独的、无意义的调用。好吧。

http://blogs.msdn.com/b/wsdevsol/archive/2015/03/26/how-to-use-a-shared-user-certificate-for-https-authentication-in-an-enterprise-application.aspx

文章摘录:

但是,在允许访问存储在共享用户证书库中的证书的证书私钥之前,安全子系统需要用户确认。使事情复杂化的是,如果在代码中指定了客户端证书,则较低级别的网络功能会假定应用程序已经处理了这一点,并且不会提示用户进行确认。

如果查看与证书相关的 Windows 运行时类,您将找不到任何方法来显式请求访问证书私钥,那么应用开发人员该怎么办?

解决方案是使用选定的证书对一些小数据进行“签名”。当应用程序调用 CryptographicEngine.SignAsync 时,底层代码请求访问私钥以进行签名,此时会询问用户是否允许应用程序访问证书私钥。请注意,您必须调用此函数的“异步”版本,因为该函数的同步版本:Sign,使用阻止确认对话框显示的选项。

例如:

public static async Task<bool> VerifyCertificateKeyAccess(Certificate selectedCertificate)
{
    bool VerifyResult = false;  // default to access failure
    CryptographicKey keyPair = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync(
                                        selectedCertificate, HashAlgorithmNames.Sha1, 
                                        CryptographicPadding.RsaPkcs1V15);
    String buffer = "Data to sign";
    IBuffer Data = CryptographicBuffer.ConvertStringToBinary(buffer, BinaryStringEncoding.Utf16BE);

    try
    {
        //sign the data by using the key
        IBuffer Signed = await CryptographicEngine.SignAsync(keyPair, Data);
        VerifyResult = CryptographicEngine.VerifySignature(keyPair, Data, Signed);
    }
    catch (Exception exp)
    {
        System.Diagnostics.Debug.WriteLine("Verification Failed. Exception Occurred : {0}", exp.Message);
        // default result is false so drop through to exit.
    }

    return VerifyResult;
}

然后您可以修改前面的代码示例以在使用客户端证书之前调用此函数,以确保应用程序可以访问证书私钥。

关于c# - UWP 应用程序 HttpClient HTTPS 客户端证书问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38265687/

相关文章:

c# - Flesch-Kincaid 可读性测试

c# - Web 应用程序在 Visual Studio 和 Azure 上显示不同的屏幕

node.js - 5 分钟后 Node https 请求 ECONRESET

ssl - 'convert' http流量到https的解决方案?代理人? (中继)

wordpress - 为我的 WordPress 网站强制使用 https...特定子域除外

c# - XDocument 节点中的 Foreach

c# - 检查控制字符

c# - Linq to SQL 简单 SUM

c# - 判断 IntPtr 是指向托管内存还是非托管内存

c# - Entity Framework 批量插入抛出 KeyNotFoundException 错误