web-dev-qa-db-fra.com

La prise de contact SSL échoue dans Xamarin

J'essaie d'accéder à mon API RESTful pour récupérer des données à partir d'une base de données MySQL. Tout est configuré et fonctionne parfaitement sur mon projet C # WPF. Mais lorsque j'utilise exactement le même code dans Xamarin Forms (conçu pour Android), je ne peux pas obtenir une négociation SSL réussie avec mon serveur.

Détails du serveur

  • Cryptons le certificat SSL (définitivement valide)
  • Apache BasicAuth (.htaccess)
  • HTTPS uniquement (réécriture HTTP activée), donc port 443
  • API REST: php-crud-api (par mevdschee) pour accéder à MariaDB 10.3

J'utilise Flurl.Http (utilise HttpClient) pour établir la connexion, mais obtenez une exception sur jsonReader.Wait ():

var jsonReader = "https://example.com/my_api/api.php/records/my_table?order=id,desc&size=10"
            .WithHeader("Accept", "application/json")
            .WithBasicAuth("username", "password")
            .GetJsonAsync<JsonRootObject>();
            // Wait for completion.
            jsonReader.Wait();


Voici mon AggregateException:

System.AggregateException: One or more errors occurred. (Call failed. An error occurred while sending the request
GET https://example.com/my_api/api.php/records/my_table?order=id,desc&size=10) ---> Flurl.Http.FlurlHttpException: Call failed. An error occurred while sending the request
GET https://example.com/my_api/api.php/records/my_table?order=id,desc&size=10 ---> System.Net.Http.HttpRequestException: An error occurred while sending the request
---> System.Net.WebException: Error: TrustFailure (Authentication failed, see inner exception.) ---> System.Security.Authentication.AuthenticationException:
Authentication failed, see inner exception. ---> Mono.Btls.MonoBtlsException: Ssl error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED
at /Users/builder/jenkins/workspace/xamarin-Android-d16-1/xamarin-Android/external/mono/external/boringssl/ssl/handshake_client.c:1132
at Mono.Btls.MonoBtlsContext.ProcessHandshake () [0x00038] in <74989b9daab94528ac2c4b7da235b9c5>:0 
at Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake (Mono.Net.Security.AsyncOperationStatus status, System.Boolean renegotiate) [0x000a1] in <74989b9daab94528ac2c4b7da235b9c5>:0 
at (wrapper remoting-invoke-with-check) Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake(Mono.Net.Security.AsyncOperationStatus,bool)
at Mono.Net.Security.AsyncHandshakeRequest.Run (Mono.Net.Security.AsyncOperationStatus status) [0x00006] in <74989b9daab94528ac2c4b7da235b9c5>:0
at Mono.Net.Security.AsyncProtocolRequest.ProcessOperation (System.Threading.CancellationToken cancellationToken) [0x000ff] in <74989b9daab94528ac2c4b7da235b9c5>:0
at Mono.Net.Security.AsyncProtocolRequest.StartOperation (System.Threading.CancellationToken cancellationToken) [0x0008b] in <74989b9daab94528ac2c4b7da235b9c5>:0 


Ce que j'ai essayé/ce que je sais

  • Code fonctionne parfaitement dans WPF
  • Le même code exact (copier-coller) ne pas fonctionne dans Xamarin Forms (testé sur Android Pie)
  • ne fonctionne pas dans l'émulateur ni dans l'appareil dédié
  • accéder à REST API via le navigateur fonctionne et fournit les résultats comme prévu (testé sur mon PC, l'émulateur dans Chrome et mon dédié) Android)
  • changer l'implémentation HttpClient ou l'implémentation SSL/TLS sous Propriétés du projet -> Android Options -> Avancé n'aide pas

Pourquoi ma négociation SSL échoue-t-elle? Que fait Xamarin différemment de WPF?

6
MadWalnut

Il s'est avéré être un erreur de configuration Apache . J'ai vérifié mon domaine et j'ai remarqué une erreur. Cela a été corrigé en ajoutant le fichier de chaîne du certificat dans mes directives Apache:

SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem

La dernière ligne était la manquante. Bizarre que les navigateurs et WPF aient fait confiance au certificat même sans le fichier de chaîne. Quoi qu'il en soit, maintenant cela fonctionne également sur Android.

En attendant, j'utilise ce morceau de code pour désactiver la validation SSL dans mon application:

// This disables the SSL certificate validity check.
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

Ce code est dangereux et ne doit être utilisé que pour les tests.

1
MadWalnut

votre Flurl.Http peut échouer en raison de l'utilisation de 2 types de projets différents (standard .net vs bibliothèque de classes - j'ai eu exactement le même problème avec le client http que j'ai écrit)

essayez un autre client http pour la norme .net.

dans tous les cas, vous pouvez écrire votre propre client http et déboguer - c'est ma recommandation.
si vous êtes toujours coincé - réécrivez, je vous aiderai.

0
Ami Vaknin