iOS 中HTTPS 的使用

谣言四起,大限将至。各种谣言皆因苹果开发者大会开始,从那个时间开始,都说2017年1月1日为HPPTS即将开始的日子。从此大航海时代就要开始了。从此就成了我挥之不去的心魔,吓得本大少和服务器端调呀调。总算调好了。好吧,我们聊聊HTTPS。

一、HTTPS

HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由网景公司(Netscape)进行,并内置于其浏览器Netscape Navigator中,提供了身份验证与加密通讯方法。(摘自百度百科)

PKI(公钥基础设施)技术是HTTPS的基础,PKI与非对称密钥加密技术密切相关,包括消息摘要、数字签名和加密服务,而数字证书以及证书机构(CA – Certificate Authority)是PKI中的重要概念。

二、Apple CSR CER P12 mobileprovition 到底是什么

  • CSR(Certificate Signing Request)钥匙串文件 为生成证书做基础,要生成CER证书必须要有CSR私钥,此私钥包含了用户自己的一些信息。这个文件是保存在我们的mac的(keychain)里面的, 此文件包含了(公钥和私钥)

  • CER 包含了开发者信息和公钥

  • P12 它不仅包含CER的信息,还有私钥信息,即: P12备份文件 = CER文件 + 私钥;所以有了这个p12就再也不用担心证书丢失了

  • mobileprovition 包含了上述所有内容 Certificate && App ID && Device, 这个Provisioning Profile文件会在打包时嵌入到.ipa的包里。本人理解的是 可以真机调试的凭证。

三、App Transport Security

iOS9中新增App Transport Security(简称ATS)特性, 主要使到原来请求的时候用到的HTTP,都转向TLS1.2协议进行传输。这也意味着所有的HTTP协议都强制使用了HTTPS协议进行传输。
一般我们如果还是使用的http,不更新的话,可通过在 Info.plist 中声明,倒退回不安全的网络请求


111.png

然后好像我说这么多是不是一点屌用都没用?想知道这么改不?接下来我们继续说正事了。我这里简单说下双向认证的自签名HTTPS证书的使用。放心,不坑。

准备证书

首先找后台要一个证书(SSL证书,一般你跟后台说要弄https,然后让他给你个证书,他就知道了),
我们需要的是.cer的证书。但是后台可能给我们的是.crt的证书。
我们需要转换一下:打开终端 -> cd到.crt证书路径 -> 输入openssl x509 -in 你的证书.crt -out 你的证书.cer -outform der
证书就准备好了,拖入工程,记得选copy。一般叫做servicer.cer
--此段引用自大神vision_colion的文章,他文章里面有单向认证的哦。
然后我们还得需要一个client.p12证书.还是问服务器端给。

屏幕快照 2016-12-15 下午2.45.30.png

屏幕快照 2016-12-15 下午2.47.06.png
//AFNetWoking3.0以上适用
- (void)testAFNetWorking{

 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;

 _manager = [AFHTTPSessionManager manager];
 _manager.securityPolicy = policy;
 _manager.requestSerializer = [AFHTTPRequestSerializer serializer];
 _manager.responseSerializer = [AFHTTPResponseSerializer serializer];
 _manager.responseSerializer.acceptableContentTypes =  [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", nil];
 //    [manager.securityPolicy setAllowInvalidCertificates:YES];
 //关闭缓存避免干扰测试r
 _manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
 [_manager setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) {
 NSLog(@"setSessionDidBecomeInvalidBlock");
 }];
 __weak typeof(self)weakSelf = self;
 [_manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) {
 NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
 __autoreleasing NSURLCredential *credential;
 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 {
 // client authentication
 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;
 }
 }
 }
 *_credential = credential;
 return disposition;
 }];

[_manager POST:@"https://192.168.0.51/dw-api-V2.0/user/login.p" parameters:@{@"yhzh":@"18639398700",@"infoMap":@"g+bc4UTf3wHjabyKW+RYqcervD+/HSJXFIRKdVCQYldN5j85x//6eVUUZsidGrUpE+MJCvHdo7/E4EjNT+hjvnYa5qJ9ep0maOWfvq6AkIinjjc9cQJ0cfEAsg2LnV17hJKi3hCRrjbQJfAqUB2C3IetHK9Gg0voOmcTK2IA1J/V+KRcCtb1XncXDxVnXiUT/qBIQKPEg3/dt5ISLHpdXQ=="} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    NSString *message = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
    NSLog(@"%@",message);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    NSLog(@"%@",error);
}];
}

//验证你P12证书的
+ (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {
    OSStatus securityError = errSecSuccess;
    //client certificate password 你的p12密码
    NSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@"123456"
                                                                 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;
}

参考文档

苹果官方文档
lanp74的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容