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.
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
Pourquoi ma négociation SSL échoue-t-elle? Que fait Xamarin différemment de WPF?
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.
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.