什么是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
如果您觉得我的文章给了您帮助,请为我买一杯饮料吧!以下是我的支付宝,意思一下我将非常感激!
相关推荐
实现HTTPS的双向认证,防止MITM(中间人攻击),示例展示了AFNetworking的推荐使用方式、双向认证、UIWebView的双向认证、密码强度检测,最新代码请移步:https://github.com/iFindTA/NHCerSecurityPro
UIWebView实现图文混排
在日版iPhone5,10.3.3 系统上,有一些遗留问题,先不管了 ...在UIWebView时代,UIWebView的delegate没有处理双向认证的方法,需要在shouldStartLoadWithRequest方法中将请求拦截使用NSURLConnectio
IOS自定义请求uiwebview的loading框 支持文字和转圈特效同时存在 动态显示 调用方便
NSURLCache让本地数据来代替远程UIWebView请求
UIWebView包含一个scrollView组件,用来将关联web内容实现滚动效果,页面滚动后的UIWebView的面板周围会出现阴影效果,该效果是在四周添加UIImageView实现的,因此移除这种阴影效果的代码如下: ? 1 2 3 4 5 ...
这是我在学习ios的过程中写的一个demo,使用UIWebView实现一个简单的浏览器
两步实现iOS UIWebView 通过 cookie 完成自动登录。
UIWebView+html+css,实现UIWebView中可点击链接,并且可显示gif动画效果
UIWebView 组件来作为混合模式开发的桥梁,用过UIWebView组件的开发者都知道,当UIWebView加载显示HTML页面时,组件本身提供了一些系统默认的交互行为,这篇文章给大家分享的是iOS UIWebView实现禁止用户复制剪切...
NULL 博文链接:https://re-reference.iteye.com/blog/1391408
UIWebView和js交互 里边自己写了个H5方便大家理解
IOS开发中因为引入cocos2dx,导致代码审核不通过无法提交( Apple will stop accepting submissions of apps that use UIWebView APIs )。该问题的解决方案有两种:1)升级Cocos2dx的版本,在查看Cocoas官网及Cocoas...
UIWebView Web 网页 Demo 代码
使用UIWebView和JS进行交互,可以OC操作js,也可以JS对OC进行交互
一个利用继承NSURLCache来达到利用本地数据代替远程UIWebView请求的实例,非常实用。
网页视图的基本使用,网络资源地址字符串的处理,UIWebView属性与协议的综合使用;
UIWebView原生与H5交互,pre;confirm;等包含三个H5页面跳转的交互demo
这是iPhone开发之UIWebView示例程序,具体参考: http://blog.csdn.net/htttw/article/details/7888557