服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS实用教程之Https双向认证详解

iOS实用教程之Https双向认证详解

2021-03-17 15:56明仔Su IOS

这篇文章主要给大家介绍了关于iOS中Https双向认证的相关资料,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友可以参考借鉴,下面来一起看看吧。

前言

年前的时候,关于苹果要强制https的传言四起,虽然结果只是一个“谣言”,但是很明显的这是迟早会到来的,间接上加速了各公司加紧上https的节奏,对于ios客户端来说,上https需不需要改变一些东西取决于---------对,就是公司有没有钱。土豪公司直接买买买,ios开发者只需要把http改成https完事。然而很不幸,我们在没钱的公司,选择了自签证书。虽然网上很多关于https的适配,然而很多都是已过时的,这里我们主要是讲一下https双向认证

【证书选择】自签

【网络请求】原生nsurlsession或者afnetworking3.0以上版本

【认证方式】双向认证

https双向认证过程

先来了解一下双向认证的大体过程:(图片来自网络,如果是某位博主原创的请私信我)

iOS实用教程之Https双向认证详解

下面我们一步步来实现

1、设置服务端证书

?
1
2
3
4
5
6
7
nsstring *certfilepath = [[nsbundle mainbundle] pathforresource:@"server" oftype:@"cer"];
nsdata *certdata = [nsdata datawithcontentsoffile:certfilepath];
nsset *certset = [nsset setwithobject:certdata];
afsecuritypolicy *policy = [afsecuritypolicy policywithpinningmode:afsslpinningmodecertificate withpinnedcertificates:certset];
policy.allowinvalidcertificates = yes;
policy.validatesdomainname = no;
self.afnetworkingmanager.securitypolicy = policy;

2、处理挑战

原生的nsurlsession是在

?
1
- (void)urlsession:(nsurlsession *)session didreceivechallenge:(nonnull nsurlauthenticationchallenge *)challenge completionhandler:(nonnull void (^)(nsurlsessionauthchallengedisposition, nsurlcredential * _nullable))completionhandler

代理方法里面处理挑战的,再看看afnetworking在该代理方法里处理的代码

?
1
2
3
4
5
if (self.taskdidreceiveauthenticationchallenge) {
 disposition = self.taskdidreceiveauthenticationchallenge(session, task, challenge, &credential);
} else {
 ...
}

我们只需要给它传递一个处理的block

?
1
2
3
[self.afnetworkingmanager setsessiondidreceiveauthenticationchallengeblock:^nsurlsessionauthchallengedisposition(nsurlsession*session, nsurlauthenticationchallenge *challenge, nsurlcredential *__autoreleasing*_credential) {
  ...
}

根据传来的challenge生成disposition(应对挑战的方式)和credential(客户端生成的挑战证书)

3、服务端认证

当challenge的认证方法为nsurlauthenticationmethodservertrust时,需要客户端认证服务端证书

?
1
2
3
4
5
6
7
8
9
10
11
12
//评估服务端安全性
if([weakself.afnetworkingmanager.securitypolicy evaluateservertrust:challenge.protectionspace.servertrust fordomain:challenge.protectionspace.host]) {
    //创建凭据
    credential = [nsurlcredential credentialfortrust:challenge.protectionspace.servertrust];
    if(credential) {
     disposition =nsurlsessionauthchallengeusecredential;
    } else {
     disposition =nsurlsessionauthchallengeperformdefaulthandling;
    }
   } else {
    disposition = nsurlsessionauthchallengecancelauthenticationchallenge;
   }

4、客户端认证

认证完服务端后,需要认证客户端

由于是双向认证,这一步是必不可省的

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
secidentityref identity = null;
sectrustref trust = null;
nsstring *p12 = [[nsbundle mainbundle] pathforresource:@"client"oftype:@"p12"];
nsfilemanager *filemanager =[nsfilemanager defaultmanager];
 
if(![filemanager fileexistsatpath:p12])
{
 nslog(@"client.p12:not exist");
}
else
{
 nsdata *pkcs12data = [nsdata datawithcontentsoffile:p12];
 
 if ([[weakself class]extractidentity:&identity andtrust:&trust frompkcs12data:pkcs12data])
 {
  seccertificateref certificate = null;
  secidentitycopycertificate(identity, &certificate);
  const void*certs[] = {certificate};
  cfarrayref certarray =cfarraycreate(kcfallocatordefault, certs,1,null);
  credential =[nsurlcredential credentialwithidentity:identity certificates:(__bridge nsarray*)certarray persistence:nsurlcredentialpersistencepermanent];
  disposition =nsurlsessionauthchallengeusecredential;
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
+ (bool)extractidentity:(secidentityref*)outidentity andtrust:(sectrustref *)outtrust frompkcs12data:(nsdata *)inpkcs12data {
 osstatus securityerror = errsecsuccess;
 //client certificate password
 nsdictionary*optionsdictionary = [nsdictionary dictionarywithobject:@"your p12 file pwd"
                 forkey:(__bridge id)ksecimportexportpassphrase];
 
 cfarrayref items = cfarraycreate(null, 0, 0, null);
 securityerror = secpkcs12import((__bridge cfdataref)inpkcs12data,(__bridge cfdictionaryref)optionsdictionary,&items);
 
 if(securityerror == 0) {
  cfdictionaryref myidentityandtrust =cfarraygetvalueatindex(items,0);
  const void*tempidentity =null;
  tempidentity= cfdictionarygetvalue (myidentityandtrust,ksecimportitemidentity);
  *outidentity = (secidentityref)tempidentity;
  const void*temptrust =null;
  temptrust = cfdictionarygetvalue(myidentityandtrust,ksecimportitemtrust);
  *outtrust = (sectrustref)temptrust;
 } else {
  nslog(@"failedwith error code %d",(int)securityerror);
  return no;
 }
 return yes;
}

原生nsurlsession双向认证

在原生的代理方法里面认证就行,代码基本和afnetworking的一致,注意最后需要调用

?
1
completionhandler(nsurlsessionauthchallengeusecredential, credential);

来执行回调操作

关于uiwebview的https双向认证

网上的资料大体上有几种解决方法

1:跳过https认证(这还能跳过?没试过,不太靠谱)

2:中断原有的请求步骤,将request拿出来,下载完整的html代码,让webview加载该代码(在单页面展示的情况下基本满足使用,但是在部分标签不是独立跳转https路径的时候,将出现无法加载的情况,不是很好用)

?
1
2
3
4
5
6
7
8
9
10
11
12
- (bool)webview:(uiwebview *)webview shouldstartloadwithrequest:(nsurlrequest *)request navigationtype:(uiwebviewnavigationtype)navigationtype {
 nsstring * urlstring = [request.url absolutestring];
 if ([urlstring containsstring:url_api_base]) {
  [[suhttpoperationmanager manager]request:request progress:nil handler:^(bool issucc, id responseobject, nserror *error) {
   nsstring * htmlstring = [[nsstring alloc] initwithdata:responseobject encoding:nsutf8stringencoding];
   base_info_fun(@"下载html完毕");
   [self loadhtmlstring:htmlstring baseurl:nil];
  }];
  return no;
 }
 return yes;
}

3、中断原有的请求步骤,将request拿出来,完成鉴权认证之后,再让webview重新请求该request(这种方式理论上好像可以,我试过,没有成功,可能我打开的方式不正确)
4、或许,您有更好的解决方案 - -

关于代码

网上很多https双向认证的代码,基本是一样的,这里我们直接拿来用就可以,前提是我们不能单纯copy,而是在理解其实现的基础上,整合到工程中,遇到问题解决思路清晰,而不是一脸懵逼。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

原文链接:http://www.jianshu.com/p/72bf60b5f94d

延伸 · 阅读

精彩推荐
  • IOS谈一谈iOS单例模式

    谈一谈iOS单例模式

    这篇文章主要和大家谈一谈iOS中的单例模式,单例模式是一种常用的软件设计模式,想要深入了解iOS单例模式的朋友可以参考一下...

    彭盛凇11872021-01-19
  • IOSiOS APP实现微信H5支付示例总结

    iOS APP实现微信H5支付示例总结

    这篇文章主要介绍了iOS APP实现微信H5支付示例总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下...

    一张小A11332021-06-01
  • IOSxcode8提交ipa失败无法构建版本问题的解决方案

    xcode8提交ipa失败无法构建版本问题的解决方案

    xcode升级到xcode8后发现构建不了新的版本。怎么解决呢?下面小编给大家带来了xcode8提交ipa失败无法构建版本问题的解决方案,非常不错,一起看看吧...

    Cinna丶7542021-02-03
  • IOSiOS10 Xcode8适配7个常见问题汇总

    iOS10 Xcode8适配7个常见问题汇总

    这篇文章主要为大家详细汇总了iOS10 Xcode8适配7个常见问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    索马里猫10332021-02-01
  • IOSiOS中时间与时间戳的相互转化实例代码

    iOS中时间与时间戳的相互转化实例代码

    这篇文章主要介绍了iOS中时间与时间戳的相互转化实例代码,非常具有实用价值,需要的朋友可以参考下。...

    张无忌!4812021-03-09
  • IOSIOS网络请求之AFNetWorking 3.x 使用详情

    IOS网络请求之AFNetWorking 3.x 使用详情

    本篇文章主要介绍了IOS网络请求之AFNetWorking 3.x 使用详情,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    总李写代码6892021-03-04
  • IOSiOS常见的几个修饰词深入讲解

    iOS常见的几个修饰词深入讲解

    这篇文章主要给大家介绍了关于iOS常见的几个修饰词的相关资料,iOS修饰词包括assign、weak、strong、retain、copy、nonatomic、atomic、readonly、readwrite,文中通过示...

    郡王丶千夜7422021-05-10
  • IOSiOS逆向教程之logify跟踪方法的调用

    iOS逆向教程之logify跟踪方法的调用

    这篇文章主要给大家介绍了关于iOS逆向教程之logify跟踪方法调用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学...

    Mr.Guo11472021-04-28