由于以下错误消息,我们无法使用WebRequest连接到HTTPS服务器:

请求被中止:无法创建SSL/TLS安全通道。

我们知道服务器没有有效的HTTPS证书,但为了绕过这个问题,我们使用下面的代码,我们从另一个StackOverflow帖子:

private void Somewhere() {
    ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate);
}

private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
   return true;
}

问题是服务器从未验证证书,并出现上述错误而失败。有人知道我该怎么做吗?


我应该提到的是,我和一个同事几周前进行了测试,它运行得很好,与我上面写的类似。我们发现的唯一“主要区别”是,我用的是Windows 7,而他用的是Windows XP。这会改变什么吗?


当前回答

您遇到的问题是aspNet用户没有访问证书的权限。您必须使用winhttpcertcfg.exe提供访问权限

关于如何设置的示例如下: http://support.microsoft.com/kb/901183

详细信息请参见步骤2

编辑:在最新版本的IIS中,此功能内置于证书管理器工具中-可以通过右键单击证书并使用管理私钥的选项来访问。更多详情请访问:https://serverfault.com/questions/131046/how-to-grant-iis-7-5-access-to-a-certificate-in-certificate-store/132791#132791

其他回答

您可以尝试安装演示证书(一些ssl提供程序提供一个月的免费演示证书),以确定问题是否与证书有效性有关。

我在仓库和档案里都有证书。我试图连接文件,得到这个错误消息。我在店里用的那台还能用。我的最佳猜测是,当我想使用文件中的证书时,由于存储了证书而导致了某种冲突。 (同一台机器上的另一个服务使用存储中的证书,而我已经使用文件中的证书开发了一个不同的服务。直到测试之前,在开发过程中都非常有效)。

我知道这是晚回答,但当我试图从win server 2012 R2(客户端)调用API(托管在win server 2016上)时,我遇到了同样的问题

经过大量调查,该问题与操作系统级别的握手问题有关,特别是主机服务器不支持来自客户端的密码列表。

当我使用Wireshark跟踪连接时,我知道了这个问题,我发现不支持发送的密码。

windows server 2012 R2对可能导致TLS/SSL握手的新密码的支持有限。

起点是当我看到这个错误“从远程端点收到致命警报。TLS协议定义的致命警报代码在事件查看器中为40”(事件查看器>>自定义视图>>管理事件))

在我的情况下,这个异常的根源是在代码的某些时候,下面的代码被调用:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

这真的很糟糕。它不仅指示. net使用不安全的协议,而且还会影响在您的应用域中随后发出的每一个新的WebClient(和类似的)请求。(请注意,传入的web请求在你的ASP中不受影响。NET应用程序,但新的WebClient请求,如与外部web服务对话,是)。

在我的情况下,它实际上并不需要,所以我可以删除该语句,所有其他的web请求重新开始正常工作。根据我在其他地方的阅读,我了解到一些事情:

This is a global setting in your appdomain, and if you have concurrent activity, you can't reliably set it to one value, do your action, and then set it back. Another action may take place during that small window and be impacted. The correct setting is to leave it default. This allows .NET to continue to use whatever is the most secure default value as time goes on and you upgrade frameworks. Setting it to TLS12 (which is the most secure as of this writing) will work now but in 5 years may start causing mysterious problems. If you really need to set a value, you should consider doing it in a separate specialized application or appdomain and find a way to talk between it and your main pool. Because it's a single global value, trying to manage it within a busy app pool will only lead to trouble. This answer: https://stackoverflow.com/a/26754917/7656 provides a possible solution by way of a custom proxy. (Note I have not personally implemented it.)

这一个是为我工作在MVC webclient

public string DownloadSite(string RefinedLink)
{
    try
    {
        Uri address = new Uri(RefinedLink);

        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

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

        using (WebClient webClient = new WebClient())
        {
            var stream = webClient.OpenRead(address);
            using (StreamReader sr = new StreamReader(stream))
            {
                var page = sr.ReadToEnd();

                return page;
            }
        }

    }
    catch (Exception e)
    {
        log.Error("DownloadSite - error Lin = " + RefinedLink, e);
        return null;
    }
}