web-dev-qa-db-ja.com

XamarinでSSLハンドシェイクが失敗する

MySQLデータベースからデータを取得するためにRESTful APIにアクセスしようとしています。すべてがセットアップされ、C#WPFプロジェクトで完全に機能します。しかし、Xamarinフォーム(Android用に構築)でまったく同じコードを使用すると、サーバーでSSLハンドシェイクを成功させることができません。

サーバーの詳細

  • SSL証明書を暗号化しましょう(完全に有効です)
  • Apache BasicAuth(.htaccess)
  • HTTPSのみ(HTTPの書き換えがオン)、ポート443
  • REST API:MariaDB 10.3にアクセスするためのphp-crud-api(mevdscheeによる)

Flurl.Http(HttpClientを使用)を使用して接続を確立していますが、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();


これは私の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 


私が試したこと/知っていること

  • コード機能 WPFで完全に
  • まったく同じコード(コピーと貼り付け)はnot Xamarin Formsで機能します(Android Pieでテスト)
  • エミュレータでも専用デバイスでも機能しない
  • REST APIをブラウザ経由でアクセスworksし、期待どおりの結果を提供します(私のPCでテスト済み、Chromeのエミュレータと専用アンドロイド)
  • プロジェクトのプロパティでHttpClient実装またはSSL/TLS実装を変更する-> Androidオプション->詳細設定は役に立たない

SSLハンドシェイクが失敗するのはなぜですか?XamarinはWPFとは異なる動作をしていますか?

6
MadWalnut

Apache設定エラー であることが判明しました。私は ドメインをチェックした でエラーに気づいた。これは、私の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

最後の行は行方不明のものでした。チェーンファイルがなくても、ブラウザーとWPFが証明書を信頼しているのは奇妙です。とにかく、今ではAndroidでも動作します。

それまでの間、このコードを使用して、アプリのSSL検証を無効にしています。

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

そのコードはunsafeであり、テストにのみ使用する必要があります。

1
MadWalnut

2つの異なるプロジェクトタイプの使用が原因でFlurl.Httpが失敗する可能性があります(.net標準とクラスライブラリ-私が書いたhttpクライアントでまったく同じ問題が発生しました)

.net標準の別のhttpクライアントを試してください。

いずれにせよ、独自のhttpクライアントを作成してデバッグすることができます。これが私の推奨事項です。
それでも立ち往生している場合-返信して私がお手伝いします。

0
Ami Vaknin