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

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

服务器之家 - 编程语言 - IOS - iOS之Https自签名证书认证及数据请求的封装原理

iOS之Https自签名证书认证及数据请求的封装原理

2021-03-05 17:19AustinKuture IOS

本篇文章主要介绍了iOS之Https自签名证书认证及数据请求的封装原理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。

摘要: 在wwdc 2016开发者大会上,苹果宣布了一个最后期限:到2017年1月1日 app store中的所有应用都必须启用 app transport security安全功能。app transport security(ats)是苹果在ios 9中引入的一项隐私保护功能,屏蔽明文http资源加载,连接必须经过更安全的https。苹果目前允许开发者暂时关闭ats,可以继续使用http连接,但到年底所有官方商店的应用都必须强制性使用ats。

项目中使用的框架是afnetworking 3.0及以上版本,由于ats的原因,ios只允许使用https开头的链接,在2016年12月30日以前苹果允许绕开ats,如下图所示:

iOS之Https自签名证书认证及数据请求的封装原理

但是从2017年1月1日开始将不再接受使用http加载资源的应用,因此本篇文章主要讲解如何使用afn进行自签名证书的通过认证(注:对于使用ca机构认证的证书不需要进行认证,直接使用https开头的链接进行数据访问和加载页面即可)项目已经上传至github(需要参考源码的话请点击链接):httpssignaturecertificate.rar

1,建立一个根类 此处命名为aknetpackegeafn

 1>  .h文件 ,创建所需要的get 与 post 方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#import <foundation/foundation.h>
 
 
typedef enum{
  
  aknetworkget ,  /**< get请求 */
  aknetworkpost = 1 /**< post请求 */
}aknetworktype;
typedef void (^httpsuccess)(id json);
typedef void (^httperro)(nserror* error);
@interface aknetpackegeafn : nsobject
 
+(instancetype)sharehttpmanager;
 
/*
 *
 networktype:请求方式 get 或 post
 signature:是否使用签名证书,是的话直接写入证书名字,否的话填nil
 api:请求的url接口
 parameters:请求参数
 sucess:请求成功时的返回值
 fail:请求失败时的返回值
 *
 */
 
- (void)networktype:(aknetworktype)networktype signature:(nsstring *)signature api:(nsstring *)api parameters:(nsdictionary *)parameters success:(httpsuccess)sucess fail:(httperro)fail;
 
@end

2> .m文件,导入头文件afnetworking.h 新建manager 属性并实现sharehttpmanager类方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#import "aknetpackegeafn.h"
#import "afnetworking.h"
 
@interface aknetpackegeafn()
 
@property (nonatomic,strong) afhttpsessionmanager *manager;
 
@end
 
@implementation aknetpackegeafn
 
 
+(instancetype)sharehttpmanager{
  static dispatch_once_t onece = 0;
  static aknetpackegeafn *httpmanager = nil;
  dispatch_once(&onece, ^(void){
    httpmanager = [[self alloc]init];
  });
  return httpmanager;
}

2,get 与post 方法的实现

使用时将后台所给的证书转换为 .cer格式 拖入项目根目录中,在方法中进行绑定即可例如后台给的证书名为:kuture.crt  收到证书后双击进行安装,然后打开钥匙串,将名为kuture的证书右击导出,选择后缀为.cer 然后确定即可 如下图所示:

iOS之Https自签名证书认证及数据请求的封装原理  -->   iOS之Https自签名证书认证及数据请求的封装原理  -->

iOS之Https自签名证书认证及数据请求的封装原理 --> iOS之Https自签名证书认证及数据请求的封装原理

get 与 post 实现方法的封装

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
- (void)networktype:(aknetworktype)networktype signature:(nsstring *)signature api:(nsstring *)api parameters:(nsdictionary *)parameters success:(httpsuccess)sucess fail:(httperro)fail{
  
  //开启证书验证模式
  afsecuritypolicy *securitypolicy = [afsecuritypolicy policywithpinningmode:afsslpinningmodecertificate];
  
  //是否允许使用自签名证书
  signature == nil ? (void)(securitypolicy.allowinvalidcertificates = no):(securitypolicy.allowinvalidcertificates = yes);
  
  //是否需要验证域名
  securitypolicy.validatesdomainname = no;
  
  _manager = [[afhttpsessionmanager alloc]initwithbaseurl:[nsurl urlwithstring:api]];
  _manager.responseserializer = [afjsonresponseserializer serializer];
  _manager.securitypolicy = securitypolicy;
  _manager.responseserializer.acceptablecontenttypes = [nsset setwithobjects:@"application/json",@"application/xml",@"text/xml",@"text/json",@"text/plain",@"text/javascript",@"text/html", nil];
  
  if (signature != nil){
    
    __weak typeof(self) weakself = self;
    [_manager setsessiondidreceiveauthenticationchallengeblock:^nsurlsessionauthchallengedisposition(nsurlsession *session, nsurlauthenticationchallenge *challenge, nsurlcredential *__autoreleasing *_credential) {
      
      //获取服务器的 trust object
      sectrustref servertrust = [[challenge protectionspace] servertrust];
      
      //导入自签名证书
      nsstring *cerpath = [[nsbundle mainbundle] pathforresource:@"你的证书名字" oftype:@"cer"];
      nsdata *cerdata = [nsdata datawithcontentsoffile:cerpath];
      
      if (!cerdata) {
        
        nslog(@"==== .cer file is nil ====");
        
        return 0;
      }
      
      nsarray *cerarray = @[cerdata];
      weakself.manager.securitypolicy.pinnedcertificates = cerarray;
      seccertificateref caref = seccertificatecreatewithdata(null, (__bridge cfdataref)cerdata);
      nscassert(caref != nil, @"caref is nil");
      
      nsarray *caarray = @[(__bridge id)(caref)];
      nscassert(caarray != nil, @"caarray is nil");
      
      //将读取到的证书设置为servertrust的根证书
      osstatus status = sectrustsetanchorcertificates(servertrust, (__bridge cfarrayref)caarray);
      sectrustsetanchorcertificatesonly(servertrust, no);
      nscassert(errsecsuccess == status, @"sectrustsetanchorcertificates failed");
      
      //选择质询认证的处理方式
      nsurlsessionauthchallengedisposition disposition = nsurlsessionauthchallengeperformdefaulthandling;
      __autoreleasing nsurlcredential *credential = nil;
      
      //nsurlauthenticationmethodservertrust质询认证方式
      if ([challenge.protectionspace.authenticationmethod isequaltostring:nsurlauthenticationmethodservertrust]) {
        //基于客户端的安全策略来决定是否信任该服务器,不信任则不响应质询
        if ([weakself.manager.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;
        }
        
      } else {
        
        disposition = nsurlsessionauthchallengeperformdefaulthandling;
      }
      
      return disposition;
    }];
  }
  
  if (networktype == 0){
    
    [_manager get:api parameters:parameters progress:^(nsprogress * _nonnull uploadprogress) {
    } success:^(nsurlsessiondatatask * _nonnull task, id _nullable responseobject) {
      
      if (sucess){
        
        sucess(responseobject);
      }else{
        
        nslog(@"链接异常或网络不存在");
      }
    } failure:^(nsurlsessiondatatask * _nullable task, nserror * _nonnull error) {
      
      fail(error);
    }];
 
  }else if (networktype == 1){
    
    
    [_manager post:api parameters:parameters progress:^(nsprogress * _nonnull uploadprogress) {
    } success:^(nsurlsessiondatatask * _nonnull task, id _nullable responseobject) {
      
      if (sucess){
        
        sucess(responseobject);
      }else{
        
        nslog(@"链接异常或网络不存在");
      }
    } failure:^(nsurlsessiondatatask * _nullable task, nserror * _nonnull error) {
      
      fail(error);
    }];
 
  
}

2  使用方法,在需要进行数据获取或传递的类里面,直接导入头文件 aknetpackegeafn.h ,并实现方法即可,如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//创建对象
  //如果是自签名证书,使用前先到aknetpackegeafn相应的方法里进行证书的绑定(证书直接拖入项目中)即可
  /*
   *
   networktype:请求方式 get 或 post
   signature:是否使用签名证书,是的话直接写入证书名字,否的话填nil
   api:请求的url接口
   parameters:请求参数
   sucess:请求成功时的返回值
   fail:请求失败时的返回值
   *
   */
  
  aknetpackegeafn *nethttps = [aknetpackegeafn sharehttpmanager];
  [nethttps networktype:请求类型 signature:证书名称 api:请求url parameters:参数 success:^(id json) {
    
    nslog(@"json:%@",json);
  } fail:^(nserror *error) {
    
    nslog(@"error:%@",error);
  }];

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://my.oschina.net/Kuture/blog/804524

延伸 · 阅读

精彩推荐
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17