c # - WebClient.DownloadString med HTTPS 'Autentificering eller dekryptering er mislykket'

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg laver et spil ved hjælp af Unity Engine (2017.2.0f3) på Windows 10 , hvor jeg forsøger at få HTML'en fra en webside. Efter min viden bruger Unity Mono C # kompilatoren og runtime v2.0 (ifølge resultaterne af at køre mono --version i UnityEditorDataMonoin), men også v5.0.1 (ifølge resultaterne af at køre mono --version i UnityEditorDataMonoBleedingEdgein). Jeg bruger i øjeblikket HTML Agility Pack til parsering. Når du forsøger at få adgang til et HTTP sikret websted, f.eks. Dictionary.com, virker alt som forventet, men uanset hvad jeg gør, kan jeg ikke få adgang til et HTTPS sikret websted, sådan som urbandictionary.com (Rediger: Tilsyneladende er problemet specifikt for dette websted, fordi efter import af certifikater ved hjælp af mozroots kan github.com fås) og altid modtage undtagelsen: TlsException: The authentication or decryption has failed. Jeg er klar over at HTML Agility Pack ikke understøtter HTTPS , og har skrevet min kode i henhold til dette svar. Jeg har prøvet løsningen beskrevet her og her, men til ingen nytte. Jeg har prøvet at køre mozroots, som jeg fandt i PathTo/Unity/Editor/Data/MonoBleedingEdge/lib/mono/4.5/mozroots, med --import, --sync , og --quiet flag, men den samme undtagelse kastes (hvis dette fungerede, er jeg skeptisk over dens bærbarhed, men måske kunne jeg implementere min egen version af mozroots, som foreslået af kommentarerne). 'Jeg har fået besked om, at versionen af ​​ Mono som Enhed bruger ikke understøtter TLS 1.2 , hvilket er problematisk. Er der ingen løsning på dette problem, er der nogen løsninger? [24] [25] [26] [29]


Bemærk: forkortet for klarhed


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.
     }
}


Loggen er som følger:


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)


Rediger: Jeg har forsøgt at opdatere runtime versionen. Den eneste mulighed var at skifte fra .Net 3.5 til 4.6 i Projektindstillinger-> Player menuen, som er eksperimentel. Jeg får stadig en undtagelse, når koden køres, men outputloggen er lidt anderledes.


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)

Bedste reference


Efter en grundig undersøgelse viser det sig, at versionen af ​​ Mono som Enhed (2017.2.0f3) , der aktuelt bruger, understøtter ikke TLS 1.2 som forklaret af en udvikler her. En omhyggelig undersøgelse af undtagelsesloggen viser også, at internt er arven bakken brugt: Mono.Net.Security.Private.LegacySslStream i modsætning til Mono.Net.Security.Private.SslStream. Fra nu af vil den eneste løsning indebære tredjepartsbiblioteker eller løsninger. [30]


Takket være @Evk for at pege mig i den rigtige retning.

Andre referencer 1


Dette problemtal skyldes HTTP-protokollen. Hvis serveren bruger sikker HTTP (faktisk HTTPS), kan fejlen opstå, når den underliggende protokol ikke håndterer X509 Certificate.


Prøv at ændre denne linje:


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


til:


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


Eller alternativt, anvend validering tilbagekaldelsen til det globale filter ved hjælp af:


ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;


før ethvert HttpWebRequest objekt oprettes i din kode.


Hvis du vil håndtere certifikatvalideringen mere omhyggeligt, implementer tilbagekaldelsen som vist her: https://msdn.microsoft.com/en-us/library/office/dd633677[31]


Dette bør løse dit problem.