最近为了满足苹果的 https 要求, 经过努力终于写出了方法

验证 SSL 证书是否满足 ATS 要求

nscurl --ats-diagnostics --verbose https://你的域名

PASS 符合要求

输出满足 ATS 的证书

openssl s_client -connect 你的域名:443 </dev/null 2>/dev/null | openssl x509 -outform DER > https.cer

1. 针对 AFNetWorking (2.6.0之前的版本)

AFSecurityPolicy分三种验证模式:

AFSSLPinningModeNone

这个模式表示不做SSL pinning,
只跟浏览器一样在系统的信任机构列表里验证服务端返回的证书。若证书是信任机构签发的就会通过,若是自己服务器生成的证书就不会通过。

AFSSLPinningModeCertificate

这个模式表示用证书绑定方式验证证书,需要客户端保存有服务端的证书拷贝,这里验证分两步,第一步验证证书的域名有效期等信息,第二步是对比服务端返回的证书跟客户端返回的是否一致。

AFSSLPinningModePublicKey

这个模式同样是用证书绑定方式验证,客户端要有服务端的证书拷贝,
只是验证时只验证证书里的公钥,不验证证书的有效期等信息。只要公钥是正确的,就能保证通信不会被窃听,因为中间人没有私钥,无法解开通过公钥加密的数据。

// 正对是 app 新人的机构发布的 SSL 证书

AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

//allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO //如果是需要验证自建证书,需要设置为YES

securityPolicy.allowInvalidCertificates = YES;

//validatesDomainName 是否需要验证域名,默认为YES;

//假如证书的域名与你请求的域名不一致,需把该项设置为NO;如设成NO的话,即服务器使用其他可信任机构颁发的证书,也可以建立连接,这个非常危险,建议打开。

//置为NO,主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。

//如置为NO,建议自己添加对应域名的校验逻辑。

securityPolicy.validatesDomainName = YES;

//validatesCertificateChain 是否验证整个证书链,默认为YES

//设置为YES,会将服务器返回的Trust Object上的证书链与本地导入的证书进行对比,这就意味着,假如你的证书链是这样的:

//GeoTrust Global CA // Google Internet Authority G2

// *.google.com //那么,除了导入*.google.com之外,还需要导入证书链上所有的CA证书(GeoTrust Global CA, Google Internet Authority G2);

//如是自建证书的时候,可以设置为YES,增强安全性;假如是信任的CA所签发的证书,则建议关闭该验证,因为整个证书链一一比对是完全没有必要(请查看源代码);

securityPolicy.validatesCertificateChain = NO;  // 2.6.0之前不需要, 之后需要

requestOperationManager.securityPolicy = securityPolicy;

// 如实自建的证书

还需要把证书导入本地工程中, 并天添加以下代码

NSData *cerData = [self getSSLCerByCerName:@"本地SSL证书的名字 "];
[securityPolicy setPinnedCertificates:@[cerData]];

// 获取 SSL 证书

+ (NSData *)getSSLCerByCerName:(NSString *)cerName {
NSString *cerPath = [[NSBundle mainBundle] pathForResource:cerName
ofType:@"cer"];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
return certData;
}

2. 针对 NSURLConnection

验证证书的API

相关的Api在Security Framework中,验证流程如下:

1). 第一步,先获取需要验证的信任对象(Trust Object)。这个Trust Object在不同的应用场景下获取的方式都不一样,对于NSURLConnection来说,是从delegate方法-connection:willSendRequestForAuthenticationChallenge:回调回来的参数challenge中获取([challenge.protectionSpace serverTrust])。

2). 使用系统默认验证方式验证Trust Object。SecTrustEvaluate会根据Trust Object的验证策略,一级一级往上,验证证书链上每一级数字签名的有效性(上一部分有讲解),从而评估证书的有效性。

3). 如第二步验证通过了,一般的安全要求下,就可以直接验证通过,进入到下一步:使用Trust Object生成一份凭证([NSURLCredential credentialForTrust:serverTrust]),传入challenge的sender中([challenge.sender useCredential:cred forAuthenticationChallenge:challenge])处理,建立连接。

4). 假如有更强的安全要求,可以继续对Trust Object进行更严格的验证。常用的方式是在本地导入证书,验证Trust Object与导入的证书是否匹配。更多的方法可以查看Enforcing Stricter Server Trust Evaluation,这一部分在讲解AFNetworking源码中会讲解到。

5). 假如验证失败,取消此次Challenge-Response Authentication验证流程,拒绝连接请求。

ps: 假如是自建证书的,则不使用第二步系统默认的验证方式,因为自建证书的根CA的数字签名未在操作系统的信任列表中。

iOS授权验证的API和流程大概了解了,下面,我们看看在NSURLConnection中的代码实现:

// NSURLConnection Https 安全验证问题
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
// 针对的是自建证书, 未受安全机构信任
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
static CFArrayRef certs;
if (!certs) {
NSData*certData =[NSData dataWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:@"本地工程中的SSL证书的名字" ofType:@"cer"]];
SecCertificateRef rootcert
=SecCertificateCreateWithData(kCFAllocatorDefault,CFBridgingRetain(certData));
const void *array[1] = { rootcert };
certs = CFArrayCreate(NULL, array, 1, &kCFTypeArrayCallBacks);
CFRelease(rootcert);
}

SecTrustRef trust = [[challenge protectionSpace] serverTrust];
// 针对一个证书对应多个域名, 无需验证域名
NSMutableArray *policies = [NSMutableArray array];
// BasicX509 不验证域名是否相同
SecPolicyRef policy = SecPolicyCreateBasicX509();
[policies addObject:(__bridge_transfer id)policy];
SecTrustSetPolicies(trust, (__bridge CFArrayRef)policies);
int err;
SecTrustResultType trustResult = 0;
err = SecTrustSetAnchorCertificates(trust, certs);
if (err == noErr) {
err = SecTrustEvaluate(trust,&trustResult);
}
CFRelease(trust);
// kSecTrustResultUnspecified: 系统隐式地信任这个证书
// kSecTrustResultProceed: 用户加入自己的信任锚点,显式地告诉系统这个证书是值得信任的
BOOL trusted = (err == noErr)
&& ((trustResult == kSecTrustResultProceed)
|| (trustResult == kSecTrustResultUnspecified));
if (trusted) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]
forAuthenticationChallenge:challenge];
}else{
[challenge.sender cancelAuthenticationChallenge:challenge];
}
}

// SSL 证书是经过信任的机构授权的, 不用再把证书存放在本地
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
//1)获取trust object
SecTrustRef trust = challenge.protectionSpace.serverTrust;
SecTrustResultType result;

// 针对一个证书对应多个域名, 无需验证域名
NSMutableArray *policies = [NSMutableArray array];
// BasicX509 不验证域名是否相同
SecPolicyRef policy = SecPolicyCreateBasicX509();
[policies addObject:(__bridge_transfer id)policy];
SecTrustSetPolicies(trust, (__bridge CFArrayRef)policies);

//2)SecTrustEvaluate对trust进行验证
OSStatus status = SecTrustEvaluate(trust, &result);
if (status == errSecSuccess &&
(result == kSecTrustResultProceed ||
result == kSecTrustResultUnspecified)) {
//3)验证成功,生成NSURLCredential凭证cred,告知challenge的sender使用这个凭证来继续连接
NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
[challenge.sender useCredential:cred forAuthenticationChallenge:challenge];

} else {
//5)验证失败,取消这次验证流程
[challenge.sender cancelAuthenticationChallenge:challenge];
}
}

https 安全验证问题的更多相关文章

  1. linux:Nginx+https双向验证(数字安全证书)

    本文由邓亚运提供 Nginx+https双向验证 说明: 要想实现nginx的https,nginx必须启用http_ssl模块:在编译时加上--with-http_ssl_module参数就ok.另 ...

  2. 【腾讯Bugly干货分享】iOS 中 HTTPS 证书验证浅析

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/-fLLTtip509K6pNOTkflPQ 导语 本 ...

  3. nginx配置https双向验证(ca机构证书+自签证书)

    nginx配置https双向验证 服务端验证(ca机构证书) 客户端验证(服务器自签证书) 本文用的阿里云签发的免费证书实验,下载nginx安装ssl,文件夹有两个文件 这两个文件用于做服务器http ...

  4. 网络基础 记一次HTTPS证书验证测试过程

    记一次HTTPS证书验证测试过程 by:授客 QQ:1033553122 实践 1) 安装证书 选择主机A(假设10.202.95.88)上安装https证书 说明:采用https的服务器,必须安装数 ...

  5. Requests对HTTPS请求验证SSL证书

    SSL证书通过在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure socket layer(SSL)安全协议是由Netscape Communication公司设计开发.该安全协议主 ...

  6. Retrofit+OKHttp忽略https证书验证

    记录这个的原因,是因为很多时候,因为后台配置的证书不正确导致APP访问不到服务器数据,导致影响自身的开发进度.没几行代码,逻辑也清晰,所以下面就直接贴出工具类吧: package huolongluo ...

  7. https 调用验证失败 peer not authenticated

    https 调用验证失败 peer not authenticated 报错日志: Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer ...

  8. java httpclient跳过https证书验证

    httpclien调用skipHttpsUtil得wrapClient方法跳过https证书验证 SkipHttpsUtil  skipHttpsUtil=new SkipHttpsUtil();   ...

  9. Java Https双向验证

    CA: Certificate Authority,证书颁发机构 CA证书:证书颁发机构颁发的数字证书 参考资料 CA证书和TLS介绍 HTTPS原理和CA证书申请(满满的干货) 单向 / 双向认证 ...

随机推荐

  1. 微信小程序开发心得

    微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...

  2. SharpMap简析

    1.背景 因为项目需求,需要基于开源项目来对SHP进行相关操作.涉及到的主要功能就是加载SHP读取其中的属性信息和几何信息.于是选择了Sharpmap来进行,在使用中对其相关功能做了初步了解,做个总结 ...

  3. Django

    一.Django 简介 Django 是一个由 Python 写成的开放源代码的 Web 应用框架.它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是 CMS(内容管理系统) ...

  4. WebApi返回Json格式字符串

    WebApi返回json格式字符串, 在网上能找到好几种方法, 其中有三种普遍的方法, 但是感觉都不怎么好. 先贴一下, 网上给的常用方法吧. 方法一:(改配置法) 找到Global.asax文件,在 ...

  5. H3 BPM社区:流程开发者的学习交流平台

    企业上市有上市流程,融资扩充有融资流程,项目招投标有招投标流程,部门领导选拔有晋升流程,员工请假休假有请假流程,早起上班梳洗有符合自己习惯的流程--生活处处是流程,流程无处不在.但从信息化建设来说,企 ...

  6. angular中使用ngResource模块构建RESTful架构

    ngResource模块是angular专门为RESTful架构而设计的一个模块,它提供了'$resource'模块,$resource模块是基于$http的一个封装.下面来看看它的详细用法 1.引入 ...

  7. .Net中的AOP系列之《方法执行前后——边界切面》

    返回<.Net中的AOP>系列学习总目录 本篇目录 边界切面 PostSharp方法边界 方法边界 VS 方法拦截 ASP.NET HttpModule边界 真实案例--检查是否为移动端用 ...

  8. HTML5 摇一摇加强版之一次失败的探索

    最近在看设备传感器的API,当然也少不了研究一下让微信称神的“摇一摇”了.关于“摇一摇”的实现,网上很多资料所以不详细说了,但总是有布局.效果不全等各种问题,所以作为一名资深copypaster,代码 ...

  9. web前端的春天 or 噩梦

    「 微信应用号可以做什么」 简单说,微信"小程序"可以为开发者提供基于微信的表单.导航.地图.媒体和位置等开发组件,让他们在微信的网页里构建一个 HTML 5 应用.同时微信还开放 ...

  10. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...