Xamarin中的SSL握手失败

时间:2019-06-17 21:54:13

标签: c# ssl xamarin lets-encrypt flurl

我正在尝试访问我的RESTful API以从MySQL数据库检索数据。在我的C#WPF项目中,一切都已设置并完美运行。但是,在Xamarin Forms(专为Android构建)中使用完全相同的代码时,我无法与服务器成功进行SSL握手。

服务器详细信息

  • 让我们加密SSL证书(绝对有效)
  • Apache BasicAuth(.htaccess)
  • 仅HTTPS(启用HTTP重写),因此端口443
  • REST API:php-crud-api(由mevdschee提供)以访问MariaDB 10.3

我正在使用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中完美运行
  • 完全相同的代码(复制粘贴)在Xamarin Forms中(在Android Pie上进行测试)起作用
  • 在仿真器或专用设备中均不起作用
  • 通过浏览器工作访问REST API,并按预期方式提供结果(在我的PC,Chrome中的模拟器和专用的Android上进行了测试)
  • 在项目属性-> Android选项->高级下更改HttpClient实现或SSL / TLS实现无济于事

为什么我的SSL握手失败? Xamarin与WPF有何不同之处?

2 个答案:

答案 0 :(得分:0)

由于使用了两种不同的项目类型(.net标准与类库-我编写的http客户端存在完全相同的问题),因此Flurl.Http可能会失败

尝试使用其他.net标准的http客户端。

无论如何,您可以编写自己的http客户端并进行调试-这是我的建议。
如果您仍然卡住,请回信给我。

答案 1 :(得分:0)

原来是Apache configuration error。我checked my domain并发现一个错误。通过在我的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; };

该代码不安全,仅应用于测试。