使用 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 应用程序的类似代码。
我已经设法在 .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 应用程序的类似代码。