WebClient.DownloadString with HTTPS "The authentication or decryption has failed"



我正在使用 Unity Engine(2017.2.0f3) Windows 10 创建游戏来自网页的html。据我所知,Unity使用" mono " c#编译器和Runtime v2.0 (根据UnityEditorDataMonobin中的mono --version的结果),而且还 v5.0.1 (根据UnityEditorDataMonoBleedingEdgebin中的mono --version的结果)。我目前正在使用 html敏捷包进行解析。尝试访问 http 有担保网站(例如dictionary.com)时,一切都按预期工作,但是无论我做什么,我都无法访问 https 有担保网站作为urbandictionary.com(编辑:显然,问题是特定于本网站的,因为在使用 mozroots导入证书后,可以访问github.com),并且始终会收到例外: TlsException: The authentication or decryption has failed.我知道 html agility pack不支持 https ,并且根据此答案编写了我的代码。我已经尝试了这里和这里描述的解决方案,但无济于事。我已经尝试运行我在PathTo/Unity/Editor/Data/MonoBleedingEdge/lib/mono/4.5/mozroots中位于--import--sync--quiet标志的mozroots,但是抛出了同样的例外(如果确实有效,我对其可移植性表示怀疑,但也许我可以实现自己的可移植性如评论所建议的,Mozroots的版本)。另外,我已经得知 mono 的版本 unity 使用不支持 tls 1.2 ,这是有问题的。如果没有解决此问题的解决方案,是否有解决方法?

注意:为清晰度删除

class MyWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
        request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
        return request;
    }
}
class GetHtml
{
    public static void Get(string url)
    {
        string documentString = new MyWebClient().DownloadString(url);
        ...
    }
}
class CallingClass
{
     public void CallingMethod()
     {
         ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
         //With or without the above line ^, the same TlsException is thrown. 
         GetHtml.Get("https://www.urbandictionary.com/define.php?term=example");
         //HTTP works properly, but HTTPS, as in this example, does not.
     }
}

日志如下:

TlsException: The authentication or decryption has failed.
Mono.Security.Protocol.Tls.RecordProtocol.ProcessAlert (AlertLevel alertLevel, AlertDescription alertDesc)
Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult)
Rethrow as IOException: The authentication or decryption has failed.
Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult)
Rethrow as WebException: Error getting response stream (Write: The authentication or decryption has failed.): SendFailure
System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult)
System.Net.HttpWebRequest.GetResponse ()
System.Net.WebClient.GetWebResponse (System.Net.WebRequest request)
System.Net.WebClient.DownloadDataCore (System.Uri address, System.Object userToken)

编辑:我尝试更新运行时版本。唯一的选择是从 .net 3.5 更改为 project settings-> player 菜单中的 4.6 ,这是实验性的。当代码运行时,我仍然会得到一个例外,但是输出日志有些不同。

TlsException: The authentication or decryption has failed.
Mono.Security.Protocol.Tls.RecordProtocol.EndReceiveRecord (System.IAsyncResult asyncResult) (at <eb1224ae7b184cd09343d47f8a05481b>:0)
Mono.Security.Protocol.Tls.SslClientStream.SafeEndReceiveRecord (System.IAsyncResult ar, System.Boolean ignoreEmpty) (at <eb1224ae7b184cd09343d47f8a05481b>:0)
Mono.Security.Protocol.Tls.SslClientStream.NegotiateAsyncWorker (System.IAsyncResult result) (at <eb1224ae7b184cd09343d47f8a05481b>:0)
Rethrow as IOException: The authentication or decryption has failed.
Mono.Security.Protocol.Tls.SslClientStream.EndNegotiateHandshake (System.IAsyncResult result) (at <eb1224ae7b184cd09343d47f8a05481b>:0)
Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (System.IAsyncResult asyncResult) (at <eb1224ae7b184cd09343d47f8a05481b>:0)
Rethrow as IOException: The authentication or decryption has failed.
Mono.Security.Protocol.Tls.SslStreamBase.EndRead (System.IAsyncResult asyncResult) (at <eb1224ae7b184cd09343d47f8a05481b>:0)
Mono.Net.Security.Private.LegacySslStream.EndAuthenticateAsClient (System.IAsyncResult asyncResult) (at <344dc4d3f1ad41809df78607b6121a41>:0)
Mono.Net.Security.Private.LegacySslStream.AuthenticateAsClient (System.String targetHost, System.Security.Cryptography.X509Certificates.X509CertificateCollection clientCertificates, System.Security.Authentication.SslProtocols enabledSslProtocols, System.Boolean checkCertificateRevocation) (at <344dc4d3f1ad41809df78607b6121a41>:0)
Mono.Net.Security.MonoTlsStream.CreateStream (System.Byte[] buffer) (at <344dc4d3f1ad41809df78607b6121a41>:0)
System.Net.WebConnection.CreateStream (System.Net.HttpWebRequest request) (at <344dc4d3f1ad41809df78607b6121a41>:0)
Rethrow as WebException: Error: SecureChannelFailure (The authentication or decryption has failed.)
System.Net.WebClient.DownloadDataInternal (System.Uri address, System.Net.WebRequest& request) (at <344dc4d3f1ad41809df78607b6121a41>:0)
System.Net.WebClient.DownloadString (System.Uri address) (at <344dc4d3f1ad41809df78607b6121a41>:0)
System.Net.WebClient.DownloadString (System.String address) (at <344dc4d3f1ad41809df78607b6121a41>:0)

此问题计数是由HTTP协议引起的。如果服务器使用安全的HTTP(实际上HTTPS),则当基础协议无法处理X509 Certificate时,可能会创建错误。

尝试更改此行:

HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;

to:

HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest; 
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

或或者,使用:

将验证回调应用于全局过滤器
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

在您的代码中创建任何HttpWebRequest对象之前。

如果您想更仔细地处理证书验证,请在此处以show来实现回调:https://msdn.microsoft.com/en-us/library/office/dd633677

这应该解决您的问题。

经过一项严格的研究,事实证明, mono Unity(2017.2.0f3)当前使用的版本不支持 tls 1.2 ,如这里的开发人员所述。同样,对异常日志进行仔细检查表明,在内部使用遗产后端:Mono.Net.Security.Private.LegacySslStreamMono.Net.Security.Private.SslStream相反。截至目前,唯一的解决方案将涉及第三方库或解决方法。

感谢@EVK指向我的方向正确。

相关内容

最新更新