我正在使用Unity引擎(2017.2.0f3)在Windows 10上创建一个游戏,我试图从网页中获取HTML。据我所知,Unity使用“Mono”C#编译器和运行时v2.0(根据在“Unity\Editor\Data\Mono\bin”中运行“mono --version”的结果),但也使用v5.0.1(根据在“Unity\Editor\Data\MonoBleedingEdge\bin”中运行“mono --version”的结果)。我目前正在使用HTML Agility Pack进行解析。当尝试访问HTTP安全网站(如dictionary.com)时,一切正常,但无论我做什么,我都无法访问HTTPS安全网站(如urbandictionary.com)(编辑: 显然,问题是特定于这个站点的,因为使用mozroots导入证书后,可以访问github.com),并且总是收到异常:
TlsException: The authentication or decryption has failed.
我知道HTML Agility Pack不支持HTTPS,并根据this answer编写了我的代码。我尝试了here和here中描述的解决方案,但都没有成功。我尝试运行mozroots
,将其定位在PathTo/Unity/Editor/Data/MonoBleedingEdge/lib/mono/4.5/mozroots
,使用--import
、--sync
和--quiet
标志,但仍然抛出相同的异常(如果这样做可以工作,我对其可移植性持怀疑态度,但也许我可以根据评论中的建议实现自己的版本)。此外,我被告知Unity使用的Mono版本不支持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更改为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)
cert-sync
,而且mozroots
不是应该解决这个问题吗?我得到的印象是让这个项目工作的唯一方法是从套接字开始编写自己的HTTPS代码。 - Alexurbandictionary
特有的问题,因为github
可以正常工作。不过我不确定原因。我无法告诉你他们是否有特定的证书,也不知道如何获取这些信息,但在使用像Chrome或Firefox这样的Web浏览器时,它表面上看起来像任何其他网站一样运行,如果这有什么意义的话。 - Alex