我正在 Windows 10 上使用 Unity Engine(2017.2.0f3)创建一个游戏,我试图从网页上获取HTML。据我所知,Unity使用“ Mono ” C#编译器和运行时 v2.0 (根据运行mono --version
的结果在Unity\Editor\Data\Mono\bin
),还有 v5.0.1 (根据mono --version
中运行Unity\Editor\Data\MonoBleedingEdge\bin
的结果)。我目前正在使用 HTML Agility Pack 进行解析。尝试访问 HTTP 安全网站(例如dictionary.com)时,一切都按预期工作,但无论我做什么,我都无法访问 HTTPS 安全网站,例如urbandictionary.com(编辑:显然,问题是特定于此站点的,因为在使用mozroots
导入证书后,可以访问github.com),并始终收到异常:{{ 1}}我知道 HTML Agility Pack 不支持 HTTPS ,并根据this answer编写了我的代码。我尝试了here和here所描述的解决方案,但无济于事。我尝试使用TlsException: The authentication or decryption has failed.
,mozroots
和PathTo/Unity/Editor/Data/MonoBleedingEdge/lib/mono/4.5/mozroots
标记运行--import
,我位于--sync
,但会抛出相同的异常(如果这确实有效,我对它的可移植性持怀疑态度,但也许我可以按照评论的建议实现我自己的mozroots版本。另外,我被告知 Unity 使用的 Mono 版本不支持 TLS 1.2 ,这是有问题的。如果没有解决此问题的方法,是否有任何解决方法?
注意:为清晰起见删节
--quiet
日志如下:
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.
}
}
编辑:我尝试更新运行时版本。唯一的选择是在项目设置 - >播放器菜单中将 .Net 3.5 更改为 4.6 ,这是实验性的。代码运行时我仍然会遇到异常,但输出日志略有不同。
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)
答案 0 :(得分:2)
此问题计数由HTTP协议引起。如果服务器使用安全HTTP
(实际为HTTPS
),则当底层协议无法处理X509 Certificate
时,可能会创建错误。
尝试更改此行:
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;
在代码中创建任何HttpWebRequest
对象之前。
如果您想更仔细地处理证书验证,请按以下方式实施回调:https://msdn.microsoft.com/en-us/library/office/dd633677
这可以解决您的问题。
答案 1 :(得分:2)
经过一番严谨的研究后发现 Unity(2017.2.0f3)目前使用的 Mono 版本不支持 TLS 1.2 ,正如开发人员here所解释的那样。此外,仔细检查异常日志显示,在内部,正在使用旧版后端:Mono.Net.Security.Private.LegacySslStream
而不是Mono.Net.Security.Private.SslStream
。截至目前,唯一的解决方案将涉及第三方库或解决方法。
感谢@Evk指出我正确的方向。