【问题标题】:Using System.Net.WebClient with HTTPS certificate使用带有 HTTPS 证书的 System.Net.WebClient
【发布时间】:2011-09-13 13:33:11
【问题描述】:

在我的 C# Windows 客户端中,我有一个 POST 提交给“母舰”。当然,我希望提交的数据是安全的,所以我付费让 HostGator 为我颁发 SSL 证书。

我保存了 .CER 文件,并且正在构建请求:

//wrapper for WebClient object to use certificate file
class SecureWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
        string certPath = @"e:\mycertificate.cer";
        X509Certificate myCert = X509Certificate.CreateFromCertFile(certPath);
        request.ClientCertificates.Add(myCert);
        return request;
    }
}

//request
private static SecureWebClient client = new SecureWebClient();
private static NameValueCollection = new NameValueCollection();
nvc.Add(POST_ACTION, ACTION_CODE_LOGIN);
nvc.Add(POST_EMAIL, email);
nvc.Add(POST_PASSWORD, password);

sResponse = System.Text.Encoding.ASCII.GetString(client.UploadValues(BASE_URL + ACTION_PAGE, nvc));

它抛出一个 System.Net.WebException:

底层连接已关闭:发送时发生意外错误。

InnerException 是 System.IO.IOException:

由于意外的数据包格式,握手失败。

任何关于我做错了什么的见解?

【问题讨论】:

  • 你想要在客户端还是服务器上的 SSL 证书?
  • 澄清一下:你想加密通信吗(你需要服务器上的证书)?还是您想对客户端进行身份验证(您需要客户端证书)?具体来说,您需要在相关端有一个私钥(可能是一个 .PFX 文件)。
  • 我并不完全精通安全方法。我可以使用 HTTPS 协议在浏览器中访问主机站点。我想通过加密将数据发布到完全相同的服务器/站点。所以,@SLaks - 从技术上讲,我不确定我想要什么。如上所述,我只是外行知道我需要什么。
  • @Roger - 请参见上文(我只能为每条评论添加 1 个 @ 标签)

标签: c# https httpwebrequest certificate http-post


【解决方案1】:

如果您使用客户端证书并且您可以使用https://访问您的服务器那么你的代码应该是这样的:

private static WebClient client = new WebClient();
private static NameValueCollection nvc= new NameValueCollection();

nvc.Add(POST_ACTION, ACTION_CODE_LOGIN);
nvc.Add(POST_EMAIL, email);
nvc.Add(POST_PASSWORD, password);

sResponse = System.Text.Encoding.ASCII.GetString(client.UploadValues(BASE_URL + ACTION_PAGE, nvc));

只要您的 BASE_URL 使用 https://,那么所有数据(进出服务器)都会被加密。

IOW 使用 SSL/TLS 从客户端到服务器不需要客户端做任何特殊的事情(使用证书),除了使用 https:// 作为方案,因为操作系统提供保护数据传输所需的一切(例如受信任的根)。

【讨论】:

  • 我按照你说的做了——我的代码和你发布的代码一样,我的 BASE_URL 是https://www.myserver.com/,但我收到的错误消息与原帖中描述的完全相同. 现在我做错了什么?
  • 把你的问题分成几部分。首先,您可以使用 WebClient 下载您的主页(使用 myserver.com)吗?如果这不起作用,请确保它可以从 Web 浏览器运行(并检查页面属性以确保它已加密)。如果可行,请尝试不使用 SSL 的上传代码,即在 myserver.com 上以确保这部分有效。很可能有一部分无法正常工作,这会给您(和我们)一些提示来帮助您。
  • 使用client.DownloadData("https://www.myserver.com/") 工作。然后使用client.UploadValues("http://www.myserver.com/") 也可以。这是什么意思?
  • 这很奇怪,下一个逻辑上的罪魁祸首将是服务器端代码(不是我看到它如何导致该特定异常)或某些服务器配置错误。如果我有这样的问题,我会(a)安装wireshark并查看SSL数据包(但这不是一个简单的选择)然后(b)尝试使用另一种工具/语言来做同样的事情(即确保它在服务器端) .也许你应该在serverfault.com 上提问?
  • 所以我尝试了client.UploadValues("https://www.myserver.com/", nvc),它奏效了(令我惊讶)。然后我大胆地决定去争取金牌并尝试原始请求:client.UploadValues(BASE_URL + ACTION_PAGE, nvc),它工作。为什么?
【解决方案2】:

客户端证书在私钥可用的情况下才有效。这一般在使用 .cer 文件时并非如此,因为 X.509 证书包含私钥。

确保私钥可用的唯一安全方法是从证书和私钥都可用的 PKCS#12 文件加载证书(即,两者都已导出.pfx 文件)。

注意事项:

  • 我说一般是因为 Windows/CryptoAPI 有时会执行一些魔术(与 X509Certificate 一起使用时)并自动将证书与证书中的私钥相关联。钥匙店。

  • 我说的是安全,因为这也适用于 Mono,而不仅仅是 MS .NET。

【讨论】:

  • 这超出了我的想象。我在哪里获取/制作/查找 PKCS#12 文件?以及如何从中加载私钥?
  • 首先确保您想要客户端证书:-)您的源代码(错误)使用了此功能,但不清楚它是否是您想要的。如果您只想要来自服务器的“https”,那么您不需要处理来自客户端应用程序的证书。
  • 我想保护我的 WebClient.UploadValues 调用的数据。这就是我真正知道如何传达的全部内容。所以我问你:我需要_need_client证书吗?
  • 不,看我的另一个答案(不是基于客户端证书)
  • @poupou:先生,您太棒了!我被这个 .cer 问题困扰了很长一段时间,现在有了 .p12 导出的密钥,一切都可以顺利运行,而无需将密钥导入密钥库。
【解决方案3】:

听起来你是在倒退。您应该在 Web 主机/服务器上安装了 SLL 证书。然后您创建一个对 Web 服务器的 Web 请求并需要 HTTPS 协议。

【讨论】:

  • 我并不完全精通安全方法。我可以使用 HTTPS 协议在浏览器中访问主机站点。我想通过加密将数据发布到完全相同的服务器/站点。
【解决方案4】:

只需使用 RDP 连接到您的服务器

打开 IE 并转到 Internet 选项

导航到高级选项卡并启用使用 SSL 2.0 和 SSL 3.0

现在您的服务器请求将通过身份验证

【讨论】:

    猜你喜欢
    • 2013-01-20
    • 2019-11-14
    • 2013-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    • 1970-01-01
    • 2014-05-05
    相关资源
    最近更新 更多