使用 Xamarin 进行客户端证书身份验证 iOS

Client Certificate Authentication with Xamarin iOS

我已经设法在 .Net HttpWebRequest class 中成功使用客户端证书,但我现在正在尝试更新 ModernHttpClient 以支持客户端证书,因此它使用了更多用于请求的高效 iOS 库。

我修改了 NSUrlSessionHandler 中的 DidReceiveChallenge 函数以检查 ClientCertificate 挑战,并尝试遵循 https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/AuthenticationChallenges.html 上的信息并将其转换为与 Xamarin 一起使用 iOS.代码编译正确并逐步执行它不会导致打印出任何错误,但最终我仍然会收到 System.Net.WebException 消息 'The server "xxx.example.com" requires a client certificate'.

我的代码如下...

public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action<NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
{
    ...snip... 

    if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodClientCertificate)
    {
        Console.WriteLine("Client Cert!");

        var password = "xxxxx";
        var options = NSDictionary.FromObjectAndKey(NSObject.FromObject(password), SecImportExport.Passphrase);

        var path = Path.Combine(NSBundle.MainBundle.BundlePath, "Content", "client.p12");
        var certData = File.ReadAllBytes(path);

        NSDictionary[] importResult;

        X509Certificate cert = new X509Certificate(certData, password);

        SecStatusCode statusCode = SecImportExport.ImportPkcs12(certData, options, out importResult);
        var identityHandle = importResult[0][SecImportExport.Identity];
        var identity = new SecIdentity(identityHandle.ClassHandle);
        var certificate = new SecCertificate(cert.GetRawCertData());

        SecCertificate[] certificates = { certificate };
        NSUrlCredential credential = NSUrlCredential.FromIdentityCertificatesPersistance(identity, certificates, NSUrlCredentialPersistence.ForSession);
        completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);

        return;
    }

    ...snip...
}

如果您想试用 (https://github.com/MrsKensington/ModernHttpClient),我已将到目前为止的更改提交给 GitHub。顺便说一句,受测试客户端证书保护的网络服务器完全没有任何价值(只有一个 .txt 文件),证书和密码对于这个网络服务器来说是唯一的,所以我毫不犹豫地与世界分享这个。

在此先感谢您的帮助,

肯辛顿夫人

你不应该使用句柄而不是类句柄吗?

var identity = new SecIdentity(identityHandle.Handle);

到目前为止你有什么进展吗?我需要 WkWebView 应用程序的类似代码。