C# WebClient.DownloadString和HTTPS;身份验证或解密失败";

C# WebClient.DownloadString和HTTPS;身份验证或解密失败";,c#,windows,unity3d,https,mono,C#,Windows,Unity3d,Https,Mono,我在Windows 10上使用Unity Engine(2017.2.0f3)创建了一个游戏,在这个游戏中,我试图从网页中获取HTML。据我所知,Unity使用“Mono”C#编译器和运行时v2.0(根据在Unity\Editor\Data\Mono\bin中运行Mono--version的结果),但也使用v5.0.1(根据在Unity\Editor\Data\Monobledgedge\bin中运行Mono--version的结果)。我目前正在使用HTML敏捷包进行解析。当尝试访问HTTP安全

我在Windows 10上使用Unity Engine(2017.2.0f3)创建了一个游戏,在这个游戏中,我试图从网页中获取HTML。据我所知,Unity使用“Mono”C#编译器和运行时v2.0(根据在
Unity\Editor\Data\Mono\bin
中运行
Mono--version
的结果),但也使用v5.0.1(根据在
Unity\Editor\Data\Monobledgedge\bin
中运行
Mono--version
的结果)。我目前正在使用HTML敏捷包进行解析。当尝试访问HTTP安全网站时,例如,一切正常,但无论我做什么,我都无法访问HTTPS安全网站,例如(编辑:显然,问题特定于此网站,因为使用
mozroots
导入证书后,可以访问),并始终收到异常:
TlsException:身份验证或解密失败。
我知道HTML Agility Pack不支持HTTPS,并已根据编写代码。我已经尝试了描述的解决方案,但是没有效果。我试过运行
mozroot
,它位于
PathTo/Unity/Editor/Data/MonoBleedingEdge/lib/mono/4.5/mozroot
,带有
--import
--sync
--quiet
标志,但引发了相同的异常(如果这真的有效,我对它的可移植性表示怀疑,但也许我可以实现我自己的mozroots版本,正如评论中所建议的那样)。此外,我已经被告知Unity使用的Mono版本不支持TLS 1.2,这是有问题的。如果没有解决这个问题的方法,有什么解决办法吗

注:为清楚起见,删节

日志如下:

编辑:我已尝试更新运行时版本。唯一的选择是在“项目设置”->“播放器”菜单中从.Net 3.5更改为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)
TlsException:身份验证或解密失败。
Mono.Security.Protocol.Tls.RecordProtocol.EndReceiveRecord(System.IAsyncResult asyncResult)(地址:0)
Mono.Security.Protocol.Tls.SslClientStream.SafeEndReceiveRecord(System.IAsyncResult ar,System.Boolean ignoreEmpty)(位于:0)
Mono.Security.Protocol.Tls.SslClientStream.NegotiateAsyncWorker(System.IAsyncResult结果)(位于:0)
作为IOException重试:身份验证或解密失败。
Mono.Security.Protocol.Tls.SslClientStream.EndNegotiateHandshake(System.IAsyncResult结果)(at:0)
Mono.Security.Protocol.Tls.SslStreamBase.AsynchHandshakeCallback(System.IAsyncResult asyncResult)(at:0)
作为IOException重试:身份验证或解密失败。
Mono.Security.Protocol.Tls.SslStreamBase.EndRead(System.IAsyncResult asyncResult)(at:0)
Mono.Net.Security.Private.LegacySLStream.EndAuthenticateTasClient(System.IAsyncResult asyncResult)(地址:0)
Mono.Net.Security.Private.LegacySLStream.AuthenticateTasClient(System.String targetHost,System.Security.Cryptography.X509Certificates.X509CertificateCollection客户端证书,System.Security.Authentication.SslProtocols启用DSLProtocols,System.Boolean CheckCertificateReturnal)(at:0)
Mono.Net.Security.MonoTlsStream.CreateStream(System.Byte[]缓冲区)(位于:0)
System.Net.WebConnection.CreateStream(System.Net.HttpWebRequest请求)(地址:0)
以WebException的形式重试:错误:SecureChannelFailure(身份验证或解密失败。)
System.Net.WebClient.DownloadDataInternal(System.Uri地址、System.Net.WebRequest和request)(地址:0)
System.Net.WebClient.DownloadString(System.Uri地址)(地址:0)
System.Net.WebClient.DownloadString(System.String地址)(地址:0)

此问题可能是由HTTP协议引起的。如果服务器使用安全的
HTTP
(实际上是
HTTPS
),则在基础协议无法处理
X509证书时可能会产生错误

尝试更改此行:

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

或者,使用以下命令将验证回调应用于全局筛选器:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
在代码中创建任何
HttpWebRequest
对象之前

如果要更仔细地处理证书验证,请按如下所示实现回调:


这应该可以解决您的问题。

经过一些严格的研究,Mono的版本证明了Unity(2017.2.0f3)正如一位开发人员所解释的,当前使用的不支持TLS 1.2。此外,对异常日志的仔细检查表明,在内部使用的是旧的后端:
Mono.Net.Security.Private.legacyssltream
,而不是
Mono.Net.Security.Private.sstream
。目前,唯一的解决方案是ird政党图书馆或变通办法


感谢@Evk为我指出了正确的方向。

你使用的是什么版本的
Mono
以及在什么平台上?在
Unity\Editor\Data\Mono\bin
中运行版本检查后,结果是2.0。另外,我目前正在使用windows 10。@Alex Mono最初没有证书存储。它是空的。在Mono 3.12+中有它是一个工具,
cert sync
,用于将证书与系统存储中的证书同步。还可以使用
system.Diagnostics.Process.Start(“mozroots”,“导入--quiet”)强制接受Firefox信任的证书;
我的意思是在3.12之前的版本中可以强制…在命令行中插入
--sync
开关也很有用。您提到的站点(urbandictionary)仅支持TLS版本1.2。仅在版本4.8中,才在mono中添加了对该TLS版本的支持。在尝试实施您的第一个建议时,我遇到一个语法错误,错误是:
“HttpWebRequest”不包含“ServerCertificateValidationCallback”的定义,并且没有扩展方法“ServerCertificateValidationCallback”第一个论点
HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest; 
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;