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,如下图所示:

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

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

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

#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类方法

#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 然后确定即可 如下图所示:

  -->     -->

-->

GET 与 POST 实现方法的封装

- (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 ,并实现方法即可,如下所示:

//创建对象
  //如果是自签名证书,使用前先到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);
  }];

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

(0)

相关推荐

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

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

  • IOS开发 支持https请求以及ssl证书配置详解

    IOS开发 支持https请求以及ssl证书配置详解 前言: 众所周知,苹果有言,从2017年开始,将屏蔽http的资源,强推https 楼主正好近日将http转为https,给还没动手的朋友分享一二 一.证书准备 1.证书转换 在服务器人员,给你发送的crt证书后,进到证书路径,执行下面语句 // openssl x509 -in 你的证书.crt -out 你的证书.cer -outform der 这样你就可以得到cer类型的证书了.双击,导入电脑. 2.证书放入工程 1.可以直接把转换好

  • 详解iOS开发 - 用AFNetworking实现https单向验证,双向验证

    自苹果宣布2017年1月1日开始强制使用https以来,htpps慢慢成为大家讨论的对象之一,不是说此前https没有出现,只是这一决策让得开发者始料未及,博主在15年的时候就做过https的接口,深知此坑之深,原因就是自身对这方面知识不了解加上网上的资料少,除此外还有博客不知对错就互相转载,导致当时网上几乎找不到能用的代码,这一点,博主说的毫不夸张. 鉴于此,博主一直想填一下这个坑,多增加一些正确的代码,来供广大开发者使用,后来一直被搁置,经过尝试后,博主现将整理好的代码发布在这里,希望能帮到

  • iOS9苹果将原http协议改成了https协议的方法

    解决方法: 在info.plist 加入key <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> 下面给大家介绍ios中http 和https 协议的访问 最近做个项目,开始采用的是HTTP协议实现客户端和服务器端的交互,后来需要改成HTTPS协议.在修改的过程中发现了一些问题,解决方案如下:

  • iOS适配https证书问题(AFNetworking3.0为例)

    众所周知,苹果有言,从2017年开始,将屏蔽http的资源,强推https 楼主正好近日将http转为https,给还没动手的朋友分享一二 1.准备证书 首先找后台要一个证书(SSL证书,一般你跟后台说要弄https,然后让他给你个证书,他就知道了),我们需要的是.cer的证书.但是后台可能给我们的是.crt的证书.我们需要转换一下:打开终端 -> cd到.crt证书路径 -> 输入openssl x509 -in 你的证书.crt -out 你的证书.cer -outform der,证书就

  • 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.

  • iOS 基于AFNetworking下自签名证书配置的方法

    自从https推出以后,客户端对网络安全的要求程度也越来越高.甚至在iOS9之后,苹果强制要求必须支持https请求. https是什么呢?它又是如何保证数据安全的呢? 简单来说,https就是http+TLS/SSL.就是在http上又加了一层处理加密信息的模块.服务端和客户端的信息传输都会通过TLS进行加密,也就说传输中的数据都是加密的,如果不知道私钥,是无法真正知道传输内容的真正意思的. 整个https单向验证流程简单总结如下: 就是用户发起请求,服务器响应后返回一个证书,证书中包含一些基

  • 详解Nginx服务器和iOS的HTTPS安全通信

    详解Nginx服务器和iOS的HTTPS安全通信 简介 在网络通信中,使用抓包软件可以对网络请求进行分析,并进行重放攻击,重放攻击的解决方案一般是使用一个变化的参数,例如RSA加密的时间戳,但考虑到网络传输时延,时间戳需要有一定的误差容限,这样仍然不能从根本上防止重放攻击.想要较好的解决重放攻击问题,应考虑使用HTTPS通信,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输.身份认证的网络协议,比HTTP协议安全. 实现 对于用浏览器访问的网站,需要向CA申请证书才能保证HTTPS的网

  • Windows Server 2008 R2 下配置TLS1.2添加自签名证书的图文教程

    前言 2017年1月1日起App Store上的所有App应用将强制开启ATS功能. 苹果的ATS(App Transport Security)对服务器硬性3点要求: ① ATS要求TLS1.2或者更高,TLS 是 SSL 新的别称. ② 通讯中的加密套件配置要求支持列出的正向保密. ③ 数字证书必须使用sha256或者更高级的签名哈希算法,并且保证密钥是2048位及以上的RSA密钥或者256位及以上的ECC密钥. 由于领导舍不得花钱,只能辛苦我们自己搞个不花钱的证书.在网上找了一大堆各种配置

  • Android和iOS包批量重签名

    本文实例为大家分享了Android和iOS包批量重签名的具体代码,供大家参考,具体内容如下 Android篇 环境要求 1 安装winrar,然后配置winrar的环境变量,要用到winrar指令 2 配置java的bin目录到环境变量,要用到jarsigner指令 重签名步骤说明: 1 从母包复制一个子包 2 删除子包的签名文件META-INFO 3 根据需要修改子包的文件,比如渠道号文件之类 4 重签名子包 对应的python脚本 import os import sys import sh

  • iOS mobileconfig配置文件进行签名的配置方法

    配置描述文件(.mobileconfig) 是XML文件,包含设备安全策略.VPN配置信息.Wi-Fi设置.APN设置.Exchange帐户设置.邮件设置以及允许iPhone和iPod touch与企业系统配合使用的证书.本文描述了苹果开发者如何使用SSL证书对. mobileconfig进行签名,从而确保iOS系统上的app安全性. 前提条件 确保已经获取SSL数字证书.有关获取数字证书方法,可参阅如何获取数字证书. 本文使用的SSL证书文件名为mbaike.crt. 与SSL证书对应的私钥.

  • 详解如何使用openssl创建自签名证书

    目录 概览&证书的结构&证书验签 创建根证书 创建根密钥 ca.key.pem 创建根证书 ca.crt.pem * 创建根证书 ca.csr.pem ca.crt.pem 查看根证书 创建服务器证书 创建服务器密钥 server.key.pem 配置文件server.ini 生成服务器端证书==请求文件== server.csr.pem 生成服务器端证书 server.crt.pem 查看服务器端请求文件 概览&证书的结构&证书验签 创建根证书 创建根密钥 ca.key.

  • 修改Android签名证书keystore的密码、别名alias以及别名密码

    Eclipse ADT的Custom debug keystore自定义调试证书的时候,Android应用开发接入各种SDK时会发现,有很多SDK是需要靠package name和keystore的指纹hash来识别的(百度地图SDK.又或是微信sdk.新浪微博的sdk),这样如果使用默认自动生成的debug keystore的话就会给开发调试工作带来一些麻烦.因为在生成这些开放平台需要带签名的apk生成的签名信息,再去申请到最后的秘钥.这时可以通过修改正式的release keystore,生

  • 获取Android签名证书的公钥和私钥的简单实例

    本文以Android签名JKS格式的证书为例: package com.test; import java.io.FileInputStream; import java.security.Key; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import javax.crypto.Cipher; public class SignTest { pu

  • C#提示:“在证书存储区中找不到清单签名证书”的解决方法

    本文实例讲述了C#提示:"在证书存储区中找不到清单签名证书"的解决方法.分享给大家供大家参考.具体分析如下: 一.问题: 程序重新生成,提示错误:在证书存储区中找不到清单签名证书. 二.解决方法: 可能是之前部署的程序证书被我删掉了或是证书过期了,结果出现这个问题.解决方案如下: 方案1:右击项目属性->签名->为ClickOnce清单签名,将勾掉的选项去掉. 方案2:在签名中创建一个新的签名. 方案3:记事本打开相应的csproj文件,调整节点值.<SignMani

随机推荐