尽管 servicePointManager hack,WebRequest 仍无法在 Xamarin.Forms 上使用 ssl

WebRequest not working with ssl on Xamarin.Forms, despite servicePointManager hack

我正在编写一个需要从只能通过 https 访问的 REST api 读取的应用程序。我 运行 遇到请求在 Mono.Security 中失败的问题,消息为:"The authentication or decryption has failed."

我做了研究,发现默认情况下 Mono 没有任何受信任的证书。我找到的所有资源都说我可以使用

ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });

分别在 iOS 和 Droid 项目的 Main() 和 OnCreate() 方法中覆盖该检查并允许任何 ssl 证书。即使采用该解决方法,我仍然遇到相同的错误。我已经单步执行了代码并确认在 iOS 和 Android 上 运行 时执行了上述行。

我的代码在访问非 https API 时完美运行。这是一个 PCL,未共享的项目。

我在提问之前参考了这些questions/resources:

目前的代码如下:

public class PawPrintsDataConnection
{
    private string response = "";
    private Task<string> StartWebRequest(string url)
    {

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.ContentType = "application/json";
        request.Method = "GET";

        Task<WebResponse> task = Task.Factory.FromAsync (request.BeginGetResponse, asyncResult => request.EndGetResponse (asyncResult), (object)null);
        return task.ContinueWith (t => ReadStreamFromResponse (t.Result));

    }
    private string ReadStreamFromResponse(WebResponse response)
    {
        using (Stream responseStream = response.GetResponseStream ())
        using (StreamReader sr = new StreamReader (responseStream)) {
            string strContent = sr.ReadToEnd ();
            return strContent;
        }
    }

    public string getRawResponse(){
        var task = StartWebRequest(string.Format (@"https://pawprints.rit.edu/v1/petitions?key={0}&limit={1}", "apikey", 50));

        this.response = task.Result;
        return response;
    }
}


public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
    protected override void OnCreate (Bundle bundle)
    {
        ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });

        base.OnCreate (bundle);

        global::Xamarin.Forms.Forms.Init (this, bundle);

        LoadApplication (new App ());
    }
}
static void Main (string[] args)
    {
        ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });
        // if you want to use a different Application Delegate class from "AppDelegate"
        // you can specify it here.
        UIApplication.Main (args, null, "AppDelegate");
        //ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

    }

在我的研究中,我在 Xamarin bugzilla 上发现了一个可能相关的错误,但我不确定它是否适用于我正在使用的版本。我是 Xamarin dev 的新手,所以我不熟悉包含哪个版本的 Mono.security 之类的东西。 https://bugzilla.xamarin.com/show_bug.cgi?id=26658

如果有帮助,这里是异常的相关部分:

System.AggregateException: One or more errors occurred ---> System.Exception: One or more errors occurred ---> System.Exception: Error: SendFailure (Error writing headers) ---> System.Exception: Error writing headers ---> System.Exception: The authentication or decryption has failed. ---> System.Exception: The authentication or decryption has failed.


at Mono.Security.Protocol.Tls.RecordProtocol.ProcessAlert (AlertLevel alertLevel, AlertDescription alertDesc) [0x00013] in ///Library/Frameworks/Xamarin.iOS.framework/Versions/8.6.1.26/src/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:654
at Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) [0x000dc] in ///Library/Frameworks/Xamarin.iOS.framework/Versions/8.6.1.26/src/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:377

您正在访问 pawprints.rit.edu 对吗?

然后站点的证书(及其根 CA)就可以了,即 iOS 会接受它(并且 Xamarin.iOS 将信任决定委托给 iOS)。 IOW 设置委托对您没有帮助(仅用于证书,没关系)。

这里的问题是服务器 configured 只允许一小部分 TLS 1.0 密码套件。 None 其中与 HttpWebRequest 使用的 Mono 当前 SSL/TLS 实现兼容。

您最好的选择是使用 HttpClientCFNetworkHandler(对于 iOS)或第 3 方句柄(例如,ModernHttpClient 对 iOS 和Android)。这将使用本机(来自 OS)SSL/TLS 实现,它支持那些密码套件(以及更好的性能)。