iOS HTTPS接口加密和身份认证 使用AFNetworking进行双向认证

释放双眼,带上耳机,听听看~!

使用AFNetworking进行双向认证

1.1

1)在项目中导入证书sever.cer和AFNetworking框架:

2)然后到AFSecurityPolicy.m中重写+ (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode方法:

   AFNetworking2是允许内嵌证书的,通过内嵌证书,AFNetworking2通过比对服务器端证书、内嵌的证书、站点域名是否一致来验证连接的服务器是否正确。在完成以上两条的情况下,会自动扫描bundle中.cer的文件,并引入,这样就可以通过自签证书来验证服务器唯一性了。
      AFNetworking会自动去搜索mainBundle下的所有cer结尾的文件并放进内存中;再一一对比。因此在代码中可以省略不写。
 注意
一般来讲,我推荐将validatesCertificateChain设置为NO,因为并不是太有必要做CertificateChain的校验。并且,在AFNetworking
2.6.0中,也正式将validatesCertificateChain拿掉了(https://github.com/AFNetworking/AFNetworking/blob/master/CHANGELOG.md), 其原因也同样为:There was no
documented security advantage to pinning against an entire certificate chain。
因此,在2.6.0之后,可以不管这个字段。而在此之前,从效率上来说,设定为NO会是个比较明智的选择。

1.2 服务器端认证客户端

1)服务端验证客户端证书,首先把服务端的证书client.p12导入到服务端的密钥库里,同时导入工程;

2)在AFURLConnectionOperation.m中加入以下方法:

3)重写AFURLConnectionOperation.m中的- (void)connection:(NSURLConnection*)connection

 

为了方便,源代码附上:

#pragma mark – 自己添加的方法

-(OSStatus)extractIdentity:(CFDataRef)withP12Data:(SecIdentityRef *)identity{

OSStatus securityError = errSecSuccess;

CFStringRef password =__CFStringMakeConstantString(“123456″);

constvoid *keys[] = {kSecImportExportPassphrase};

const void *values[] = {password};

CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);

CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

securityError = SecPKCS12Import(withP12Data, options, &items);

if (securityError == 0) {

CFDictionaryRef ident = CFArrayGetValueAtIndex(items, 0);

const void *tempIdentity =NULL;

tempIdentity = CFDictionaryGetValue(ident,kSecImportItemIdentity);

*identity = (SecIdentityRef)tempIdentity;

}

if (options) {

CFRelease(options);

}

return securityError;

 

}

 

– (void)connection:(NSURLConnection *)connection

willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

{

NSString *thePath = [[NSBundlemainBundle] pathForResource:@”Client”ofType:@”p12″];

NSLog(@”thePaththePath == %@”,thePath);

NSData *PKCS12Data = [[NSDataalloc] initWithContentsOfFile:thePath];

CFDataRef inPKCS12Data = (__bridgeCFDataRef)PKCS12Data;

SecIdentityRef identity = NULL;

[self extractIdentity:inPKCS12Data :&identity];

SecCertificateRef certificate = NULL;

SecIdentityCopyCertificate(identity, &certificate);

const void *certs[] = {certificate};

NSURLCredential *credential = [NSURLCredentialcredentialWithIdentity:identity certificates:nilpersistence:NSURLCredentialPersistencePermanent];

[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];

}

如果是需要认证的时候不会先调用didReceiveResponse,而是先调用3)和2)的函数,NSURLAuthenticationChallenge是一个认证挑战类,也就是要求客户端进行挑战,要接收挑战也就是客户端提供挑战的凭证(用户和密码,或者客户端证书,或者信任服务器证书,或者代理),IOS提供了一个NSURLCredential的类来表示挑战凭证。可以通过如下函数来建立挑战凭证。所以访问https的时候服务器认证客户端就调用这个方法。

 

这两段代码是通过p12文件来验证服务器的,需要自己修改的地方只有一个,那就是2)中的CFStringRefpassword =CFSTR(“123456”);这是p12证书的密码,用自己的p12证书密码替换”123456″。

 

1.3控制器里如何请求

 

通过1.1和1.2我们的客户端和服务器双向认证已经设置好了,在控制器里只需要需要调用manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];的方法来进行双向认证:

然后就可以访问HTTPS的服务器了。

 

 

人已赞赏
iOS文章

iOS 有关环信 移动客服

2020-5-2 0:01:54

iOS文章

iOS开发armv6、armv7、armv7s、arm64这样四种的区别

2020-5-2 1:16:49

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索