服务器之家

服务器之家 > 正文

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

时间:2021-03-05 17:19     来源/作者:AustinKuture

摘要: 在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

标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
Intellij idea2020永久破解,亲测可用!!!
Intellij idea2020永久破解,亲测可用!!! 2020-07-29
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
返回顶部