首页 » SEO优化 » modenphp技巧_iOS 9之适配ATS

modenphp技巧_iOS 9之适配ATS

访客 2024-11-21 0

扫一扫用手机浏览

文章目录 [+]

iOS 9系统已经出来了,而网络方面的ATS(App Transport Security)特性可以说每个人都要经历。
而我这篇博客,便是结合我最近几天的经历,来谈谈从做事器到iOS客户端对ATS的适配。

一、大略谈谈ATS(App Transport Security)

modenphp技巧_iOS 9之适配ATS

ATS(App Transport Security)是为了提高App与做事器之间安全传输数据一个特性,这个特性从iOS9和OSX10.11开始涌现,它默认须要知足以下几个条件:

modenphp技巧_iOS 9之适配ATS
(图片来自网络侵删)

做事器TLS版本至少是1.2版本

连接加密只许可几种前辈的加密

证书必须利用SHA256或者更好的哈希算法进行署名,要么是2048位或者更长的RSA密钥,要么便是256位或更长的ECC密钥。

如果想理解哪几种前辈的加密是被许可的,详情请见官方文档App Transport Security Technote

二、搭建HTTPS做事器

搭建HTTPS做事器有两种办法,一种是创建证书要求,然后到威信机构认证,随之配置到做事器;其余一种是自建证书,然后配置给做事器。
第一种办法搭建的HTTPS做事器当然是最优的了,建立网站的话,直接就会被信赖,而作为移动端app的做事器时,也不须要为ATS做过多的适配。
虽然说威信的机构认证都是须要钱的,但是如今也不乏存在免费的第三方认证机构;第二种办法搭建的HTTPS做事器,对付网站来说完备不可行,用户打开时直接弹出一个警告提醒,说这是一个不受信赖的网站,让用户是否连续,体验很差,而且让用户觉得网站不屈安。
对付移动端来说,在iOS9涌现之前,这个没什么问题,但是在iOS9出来之后,第二种办法是通不过ATS特性,须要将NSAllowsArbitraryLoads设置为YES才行。
以是,我推举利用第一种办法搭建HTTPS做事器。

下面,咱们来说说这两种办法都如何进行操作。

第一种、利用CA机构认证的证书搭建HTTPS做事器

1、创建证书要求,并提交给CA机构认证

#天生私钥

openssl genrsa -des3 -out private.key 2048

#天生做事器的私钥,去除密钥口令

openssl rsa -inprivate.key -out server.key

#天生证书要求

openssl req -new-key private.key -out server.csr

将天生server.csr提交给CA机构,CA机构对它进行署名之后,然后会天生署名后的根证书和做事器证书发送给你,这个时候的证书便是CA认证之后的证书。
我们这里将根证书和做事器证书分别改名为ca.crt和serve.crt。

2、配置Apache做事器

将ca.crt、server.key、server.crt上传到阿里云做事器,利用SSH上岸进入这三个文件的目录,实行下面命令

mkdir ssl

cp server.crt /alidata/server/httpd/conf/ssl/server.crt

cp server.key /alidata/server/httpd/conf/ssl/server.key

cp demoCA/cacert.pem /alidata/server/httpd/conf/ssl/ca.crt

cp -r ssl /alidata/server/httpd/conf/

编辑/alidata/server/httpd/conf/extra/httpd-ssl.conf文件,找到SSLCertificateFile、SSLCertificateKeyFile、SSLCACertificatePath、SSLCACertificateFile进行修正:

# 指定做事器证书位置

SSLCertificateFile \"大众/alidata/server/httpd/conf/ssl/server.crt\"大众

# 指定做事器证书key位置

SSLCertificateKeyFile \"大众/alidata/server/httpd/conf/ssl/server.key\公众

# 证书目录

SSLCACertificatePath \"大众/alidata/server/httpd/conf/ssl\"大众

# 根证书位置

SSLCACertificateFile \"大众/alidata/server/httpd/conf/ssl/ca.crt\"大众

修正vhost配置vim /alidata/server/httpd/conf/vhosts/phpwind.conf

SSLCertificateFile /alidata/server/httpd/conf/ssl/server.crt

SSLCertificateKeyFile /alidata/server/httpd/conf/ssl/server.key

SSLCACertificatePath /alidata/server/httpd/conf/ssl

SSLCACertificateFile /alidata/server/httpd/conf/ssl/ca.crt

ServerName www.casetree.cn

DocumentRoot /alidata/www

末了,重启Apache做事器,在浏览器输入网址查看是否配置成功。
我这里是个人利用,申请的是免费的证书,我申请证书的网站是沃通。

第二种、自建证书配置HTTPS做事器

三、利用nscurl对做事器进行检测

搭建完HTTPS做事器之后,可以利用nscurl命令来进行检测,查看建立的HTTPS做事器是否能通过ATS特性。

nscurl --ats-diagnostics --verbose https://casetree.cn

如果HTTPS做事器能通过ATS特性,则上面所有测试案例都是PASS;如果某一项的Reuslt是FAIL,就找到ATS Dictionary来查看,就能知道HTTPS做事器不知足ATS哪个条件。
这里我前面碰到一个问题,便是自建证书的时候,通过此命令进行测试时,创造Result全是FAIL,而且在iOS的代码测试中也涌现了一个很奇怪的征象,便是相同的代码,在iOS8.4要求数据完备正常,但是在iOS9上,直接是连接失落败。
终极创造,实在便是由于自建证书不受信赖,是通不过ATS的,除非将NSAllowsArbitraryLoads设置为YES。

四、iOS客户端

在上面的第二大步骤当中,HTTPS做事器知足ATS默认的条件,而且SSL证书是通过威信的CA机构认证过的,那么我们在利用Xcode7开拓的时候,对网络的适配什么都不用做,我们也能正常与做事器通信。
但是,当我们对安全性有更高的哀求时或者我们自建证书时,我们须要本地导入证书来进行验证。

那么,如何本地导入证书进行验证呢?

在这里先提一下,由于iOS客户端支持的证书是DER格式的,我们须要创建客户端证书。
创建客户端证书,直接将做事真个CA根证书导出成DER格式就行。

openssl x509 -inform PEM -outform DER -inca.crt -out ca.cer

导入完证书之后,我们分别来说说利用NSURLSession和AFNetworking来进行本地验证。

首先,来说说利用NSURLSession验证

验证步骤如下:

导入CA根证书到工程中,即我们创建的ca.cer

获取trust object,通过SecCertificateCreateWithData方法读取导入的证书的数据天生一个证书工具,然后通过SecTrustSetAnchorCertificates 设置这个证书为trust object的信赖根证书(trusted anchor)

通过SecTrustEvaluate方法去验证trust object

下面是紧张OC实当代码,Demo工程我也放在github上了,有OC和Swift两种措辞,下载Demo请点击HTTPSConnectDemo。

- (void)viewDidLoad {

[superviewDidLoad];

//导入客户端证书

NSString cerPath = [[NSBundle mainBundle] pathForResource:@\公众ca\"大众ofType:@\"大众cer\"大众];

NSData data = [NSData dataWithContentsOfFile:cerPath];

SecCertificateRef certificate = SecCertificateCreateWithData(, (__bridge CFDataRef) data);

self.trustedCerArr = @[(__bridge_transfer id)certificate];

//发送要求

NSURL testURL = [NSURL URLWithString:@\"大众https://casetree.cn/web/test/demo.php\公众];

NSURLSession session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

NSURLSessionDataTask task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:testURL]];

[task resume];

// Do any additional setup after loading the view, typically from a nib.

}

#pragma mark - NSURLSessionDelegate

- (void)URLSession:(NSURLSession )session didReceiveChallenge:(NSURLAuthenticationChallenge )challenge

completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential __able credential))completionHandler{

OSStatus err;

NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;

SecTrustResultType trustResult = kSecTrustResultInvalid;

NSURLCredential credential = nil;

//获取做事器的trust object

SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;

//将读取的证书设置为serverTrust的根证书

err = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)self.trustedCerArr);

if(err == noErr){

//通过本地导入的证书来验证做事器的证书是否可信,如果将SecTrustSetAnchorCertificatesOnly设置为NO,则只要通过本地或者系统证书链任何一方认证就行

err = SecTrustEvaluate(serverTrust, &trustResult);

}

if(err == errSecSuccess && (trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified)){

//认证成功,则创建一个凭据返回给做事器

disposition = NSURLSessionAuthChallengeUseCredential;

credential = [NSURLCredential credentialForTrust:serverTrust];

}

else{

disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;

}

//回调凭据,通报给做事器

if(completionHandler){

completionHandler(disposition, credential);

}

}

把稳:

1、SecTrustSetAnchorCertificates方法会设置一个标示去屏蔽trust object对其它根证书的信赖;如果你也想信赖系统默认的根证书,请调用SecTrustSetAnchorCertificatesOnly方法,清空这个标示(设置为NO) 2、验证的方法不仅仅只有这一种,更多的验证方法,请参考HTTPS Server Trust Evaluation

下面,来谈谈AFNetworking是如何验证的,我们如何利用AFNetworking。

AFNetworking的证书验证事情是由AFSecurityPolicy来完成的,以是这里我们紧张来理解一下AFSecurityPolicy。
把稳:我这里利用的是AFNetworking2.6.0,它跟2.5.0是有差异的。

说到AFSecurityPolicy,我们必须要提到它三个主要的属性,如下:

@property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode;

@property (nonatomic, assign) BOOL allowInvalidCertificates;

@property (nonatomic, assign) BOOL validatesDomainName;

SSLPingMode是最主要的属性,它标明了AFSecurityPolicy因此何种办法来验证。
它是一个列举类型,这个列举类型有三个值,分别是AFSSLPinningModeNone、AFSSLPinningModePublicKey、AFSSLPinningModeCertificate。
个中,AFSSLPinningModeNone代表了AFSecurityPolicy不做更严格的验证,只假如系统信赖的证书就可以通过验证,不过,它受到allowInvalidCertificates和validatesDomainName的影响;AFSSLPinningModePublicKey是通过比较证书当中公钥(PublicKey)部分来进行验证,通过SecTrustCopyPublicKey方法获取本地证书和做事器证书,然后进行比较,如果有一个相同,则通过验证,此办法紧张适用于自建证书搭建的HTTPS做事器和须要较高安全哀求的验证;AFSSLPinningModeCertificate则是直接将本地的证书设置为信赖的根证书,然后来进行判断,并且比较本地证书的内容和做事器证书内容是否相同,来进行二次判断,此办法适用于较高安全哀求的验证。

allowInvalidCertificates属性代表是否许可不信赖的证书通过验证,默认为NO。

validatesDomainName属性代表是否验证主机名,默认为YES。

接下来,我们说下验证流程。
验证流程紧张放在AFSecurityPolicy的- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString )domain方法当中。

- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust

forDomain:(NSString )domain

{

//当利用自建证书验证域名时,须要利用AFSSLPinningModePublicKey或者AFSSLPinningModeCertificate

if(domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) {

NSLog(@\"大众In order to validate a domain name for self signed certificates, you MUST use pinning.\"大众);

returnNO;

}

NSMutableArray policies = [NSMutableArray array];

//须要验证域名时,须要添加一个验证域名的策略

if(self.validatesDomainName) {

[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];

} else{

[policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];

}

//设置验证的策略,可以是多个

SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);

//SSLPinningMode为AFSSLPinningModeNone时,allowInvalidCertificates为YES,则代表做事器任何证书都能验证通过;如果它为NO,则须要判断此做事器证书是否是系统信赖的证书

if(self.SSLPinningMode == AFSSLPinningModeNone) {

if(self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust)){

returnYES;

} else{

returnNO;

}

} elseif(!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) {

returnNO;

}

//获取做事器证书的内容

NSArray serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust);

switch(self.SSLPinningMode) {

caseAFSSLPinningModeNone:

default:

returnNO;

caseAFSSLPinningModeCertificate: {

//AFSSLPinningModeCertificate是直接将本地的证书设置为信赖的根证书,然后来进行判断,并且比较本地证书的内容和做事器证书内容是否相同,如果有一个相同则返回YES

NSMutableArray pinnedCertificates = [NSMutableArray array];

for(NSData certificateData inself.pinnedCertificates) {

[pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(, (__bridge CFDataRef)certificateData)];

}

//设置本地的证书为根证书

SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);

//通过本地的证书来判断做事器证书是否可信,不可信,则验证不通过

if(!AFServerTrustIsValid(serverTrust)) {

returnNO;

}

//判断本地证书和做事器证书的内容是否相同

NSUInteger trustedCertificateCount = 0;

for(NSData trustChainCertificate inserverCertificates) {

if([self.pinnedCertificates containsObject:trustChainCertificate]) {

trustedCertificateCount++;

}

}

returntrustedCertificateCount > 0;

}

caseAFSSLPinningModePublicKey: {

//AFSSLPinningModePublicKey是通过比较证书当中公钥(PublicKey)部分来进行验证,通过SecTrustCopyPublicKey方法获取本地证书和做事器证书,然后进行比较,如果有一个相同,则通过验证

NSUInteger trustedPublicKeyCount = 0;

NSArray publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);

//判断做事器证书的公钥与本地的证书公钥是否相同,相同则客户端认证通过

for(id trustChainPublicKey inpublicKeys) {

for(id pinnedPublicKey inself.pinnedPublicKeys) {

if(AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) {

trustedPublicKeyCount += 1;

}

}

}

returntrustedPublicKeyCount > 0;

}

}

returnNO;

}

说了验证流程,我们末了来看看AFNetworking怎么利用,代码如下:

_httpClient = [[BGAFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:baseURL]];

AFSecurityPolicy policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

//是否许可CA不信赖的证书通过

policy.allowInvalidCertificates = YES;

//是否验证主机名

policy.validatesDomainName = YES;

_httpClient.securityPolicy = policy;

这里我就没有建立Demo了,如果要看的话,可以看看我写的一个框架BGNetwork,里面的Demo对ATS进行了适配,AFNetworking的利用放在BGNetworkConnector类里面的- (instancetype)initWithBaseURL:(NSString )baseURL delegate:(id)delegate初始化方法中。

五、适配ATS

前面的内容讲述都是知足ATS特性的情形,但若是做事器是自建证书搭建的,或者TLS版本是1.0的话,做事器又不能轻易改动,那么我们客户端如何适配呢? 不急,我们可以在工程中的Info.plist文件当中进行设置,紧张参照下图:

如果是自建证书,没有经由威信机构认证的证书,那么须要将NSAllowsArbitraryLoads设置为YES才能通过。
NSAllowsArbitraryLoads为YES,以前的HTTP要求也能通过。

如果是认证过的证书,那么可以通过nscurl --ats-diagnostics --verbose https://casetree.cn这样的命令来查看做事器支持的ATS Dictionary,然后进行对应的设置。

总结

回顾前面的内容,总结一下,紧张讲了一下几点内容:

ATS须要知足的条件

如何建立证书,搭建HTTPS做事器

利用nscurl命令来检测HTTPS做事器是否知足ATS特性

客户真个适配,讲述了NSURLSession和AFNetworking的利用

讲述了如果建立的做事器不知足ATS的条件时,我们如何适配

参考

点击下图,参加CocoaChina最新活动

微旗子暗记:CocoaChinabbs

(长按上图,可自动识别二维码)

--------------------------------------

商务互助QQ:645047738

投稿邮箱:support@cocoachina.com

标签:

相关文章

大数据时代的家庭生活,变革与机遇

随着信息技术的飞速发展,大数据已成为推动社会进步的重要力量。在家庭生活中,大数据的应用也逐渐深入,不仅改变了我们的生活方式,更带来...

SEO优化 2024-12-15 阅读0 评论0

大数据时代下的转本之路,机遇与挑战并存

随着互联网技术的飞速发展,大数据已成为当今时代的重要特征。大数据在各个领域的应用日益广泛,为传统行业带来了前所未有的变革。在我国,...

SEO优化 2024-12-15 阅读0 评论0

大数据时代下的说课艺术,创新与方法

随着互联网技术的飞速发展,大数据时代已经到来。教育领域也不例外,大数据在教育教学中的应用越来越广泛。说课作为教师专业成长的重要环节...

SEO优化 2024-12-15 阅读0 评论0