当前位置:首页 > 开发 > 移动开发 > 正文

UIWebView实现https双向认证请求

发表于: 2014-08-18   作者:bewithme   来源:转载   浏览:
摘要:           什么是HTTPS双向认证我已在先前的博文 ASIHTTPRequest实现https双向认证请求 中有讲述,不理解的读者可以先复习一下。本文是用UIWebView来实现对需要客户端证书验证的服务请求,网上有些文章中有涉及到此内容,但都只言片语,没有讲完全,更没有完整的代码,让人困扰不已。但是此知

 

        什么是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 如果您觉得我的文章对您有帮助,有劳参观并收藏我的网店,谢谢。  http://mrs-x.taobao.com/

 

 

 

     

UIWebView实现https双向认证请求

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
什么是双向认证呢?简而言之,就是服务器端对请求它的客户端要进行身份验证,客户端对自己所请求的
一、背景&概念 HTTPS:在http(超文本传输协议)基础上提出的一种安全的http协议,因此可以称为安全的
SSL 的双向认证就是,客户端要获取服务端的证书,检查下服务端是不是我可以信任的主机,否则我就认
去年用tomcat、jboss配置过HTTPS双向认证,那时候主要用的是JDK自带的keytool工具。这次是用httpd +
SSL 的双向认证就是,客户端要获取服务端的证书,检查下服务端是不是我可以信任的主机,否则我就认
http://www.blogjava.net/stevenjohn/archive/2012/08/22/385989.html http://blog.csdn.net/jasonh
1、修改httpd.conf配置文件 LoadModule ibm_ssl_module modules/mod_ibm_ssl.so Listen 0.0.0.0:443
转载自:http://blog.csdn.net/troylemon/article/details/46864027 对外开放的网站一般都会提供安
  过去的十几年,网络上已经积累了大量的Web应用。如今,无论是整合原有的Web应用系统,还是进行
我们常见的SSL验证较多的只是验证我们的服务器是否是真实正确的,当然如果你访问的URL压根就错了,
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号