C# WebClient.DownloadString和HTTPS;身份验证或解密失败";
我在Windows 10上使用Unity Engine(2017.2.0f3)创建了一个游戏,在这个游戏中,我试图从网页中获取HTML。据我所知,Unity使用“Mono”C#编译器和运行时v2.0(根据在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安全
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;