什么是HTTPS双向认证我已在先前的博文 ASIHTTPRequest实现https双向认证请求
中有讲述,不理解的读者可以先复习一下。本文是用UIWebView来实现对需要客户端证书验证的服务请求,网上有些文章中有涉及到此内容,但都只言片语,没有讲完全,更没有完整的代码,让人困扰不已。但是此知识点其实还是比较重要并且是有一定难度的,在安全性要求比较高的场合比如银行APP中应该比较常用,当然你也可以用在你自己的项目中,为您的应用增加安全保护。
废话我就少说点了,来看看关键代码吧。
@interface RootViewController : UIViewController<UIWebViewDelegate,NSURLConnectionDelegate>
{
UIWebView *webView;
UIActivityIndicatorView *activityIndicatorView;
//当前的url
NSURL *_currenURL;
NSURLConnection* reUrlConnection;//重发请求
NSURLRequest* originRequest;
}
@property(nonatomic,assign,getter =isAuthed)BOOL authed;
@property(nonatomic,strong)NSURL *currenURL;
@end
以上代码是UIWebView的视图控制器的声明代码,实现以下两个代理UIWebViewDelegate,NSURLConnectionDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSString *url=[[request URL]absoluteString];
if ([url hasPrefix:@"protocol://"]) {
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"Called by JavaScript"
message:@"You've called iPhone provided control from javascript!!" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
[alert show];
return NO;
}
NSString* scheme = [[request URL] scheme];
NSLog(@"scheme = %@",scheme);
//判断是不是https
if ([scheme isEqualToString:@"https"]) {
//如果是https:的话,那么就用NSURLConnection来重发请求。从而在请求的过程当中吧要请求的URL做信任处理。
if (!self.isAuthed) {
originRequest = request;
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];
[webView stopLoading];
return NO;
}
}
return YES;
}
以上代码重载了UIWebViewDelegate中的shouldStartLoadWithRequest 方法。
- (void)connection: (NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount]== 0) {
_authed = YES;
NSString *path = [[NSBundle mainBundle]pathForResource:@"wenfeng.xu" ofType:@"pfx"];
NSData *p12data = [NSData dataWithContentsOfFile:path];
CFDataRef inP12data = (__bridge CFDataRef)p12data;
SecIdentityRef myIdentity;
SecTrustRef myTrust;
extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);
long count = SecTrustGetCertificateCount(myTrust);
NSMutableArray* myCertificates = nil;
if(count > 1) {
myCertificates = [NSMutableArray arrayWithCapacity:count];
for(int i = 1; i < count; ++i) {
[myCertificates addObject:(__bridge id)SecTrustGetCertificateAtIndex(myTrust, i)];
}
}
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:nil persistence:NSURLCredentialPersistenceNone];
assert(credential != nil);
NSLog(@"User: %@, certificates %@ identity:%@", [credential user], [credential certificates], [credential identity]);
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}else{
[challenge.sender cancelAuthenticationChallenge:challenge];
}
}
NSString *path = [[NSBundle mainBundle]pathForResource:@"wenfeng.xu" ofType:@"pfx"];
以上代码声明客户端证书的类型与名称
OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)
{
OSStatus securityError = errSecSuccess;
CFStringRef password = CFSTR("p@ssw0rd888");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import(inP12data, options, &items);
if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
*identity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
*trust = (SecTrustRef)tempTrust;
CFIndex count = CFArrayGetCount(items);
NSLog(@"Certificates found: %ld",count);
}
if (options) {
CFRelease(options);
}
return securityError;
}
以上代码实现请求前公钥与私钥的提取
CFStringRef password = CFSTR("p@ssw0rd888");
以上代码声明证书的访问密码
完整的代码已在附件中,支持自签名的服务器证书,有任何问题请联系qq 359709421
如果您觉得我的文章给了您帮助,请为我买一杯饮料吧!以下是我的支付宝,意思一下我将非常感激!