如何为 AFNetworking 创建 .cer 文件以在 iOS 应用程序包中使用
Posted
技术标签:
【中文标题】如何为 AFNetworking 创建 .cer 文件以在 iOS 应用程序包中使用【英文标题】:How to create .cer file for AFNetworking to be used in iOS app bundle 【发布时间】:2015-03-19 22:29:51 【问题描述】:我一直在网络上看到关于 .cer 文件是什么以及如何生成它以便应用程序可以通过 https 与服务器正确通信的脱节帐户。
引用this消息来源,有人说:
1) 您现在需要捆绑包中的 .cer 文件来获取链中的所有证书。因此,至少必须存在两个证书文件(您的证书和根 CA)。在我们的例子中,我们也需要一个中间体。
2) 这些证书必须按特定顺序排列。具体来说,证明您正在与之通信的主机的证书必须位于固定证书/密钥列表中的第一位。其余部分的顺序看起来并不重要。这是因为 AFSecurityPolicy 使用数组中的第一个对象来验证主机名。
3) 如果您与根域通信,则通配符证书的主机验证失败。例如,考虑指向 *.foo.com 的证书。如果您与 foo.com 通信,主机检查将失败,因为主机组件计数不匹配。我理解这种早期优化的必要性,但它甚至在达到专门处理通配符域的逻辑之前就失败了。
官方文档支持here。
我想为了生成它,必须将整个证书链的内容按特定顺序放入 .cer 文件中。我记得在某个地方看到过这个帖子,但似乎找不到。
问题是,为 AFNetworking 创建 .cer 文件的无可争议的方法是什么?
更新:
经过更多研究,在我看来,您只需获取 .crt 文件并对其执行以下操作:
openssl x509 -in www.mydomain.com.crt -out www.mydomain.com.cer -outform der
但是,即使在执行此操作并将 .cer 附加到我的应用程序包之后,我也会在此处收到错误:
+ (NSArray *)pinnedPublicKeys
static NSArray *_pinnedPublicKeys = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
NSArray *pinnedCertificates = [self pinnedCertificates];
NSMutableArray *publicKeys = [NSMutableArray arrayWithCapacity:[pinnedCertificates count]];
for (NSData *data in pinnedCertificates)
SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data);
NSParameterAssert(allowedCertificate);
错误出现在最后一行。我想在它尝试分配allowedCertificate
的前一行中,SecCertificateCreateWithData
具有以下描述:
/*!
@function SecCertificateCreateWithData
@abstract Create a certificate given it's DER representation as a CFData.
@param allocator CFAllocator to allocate the certificate with.
@param certificate DER encoded X.509 certificate.
@result Return NULL if the passed-in data is not a valid DER-encoded
X.509 certificate, return a SecCertificateRef otherwise.
*/
显然它返回一个 NULL,但我不知道为什么。我的特定证书格式正确。但是,我确实注意到pinnedCertificates
数组中还有其他“证书”,但我不知道它从哪里得到它们。我似乎也找不到它们或打印出来。据我所知,我在 app bundle 中只有一个,但它似乎显示的不止这些。
最后一行assert产生的错误是:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: allowedCertificate'
【问题讨论】:
【参考方案1】:假设您使用的是 AFNetworking 2.5,步骤如下所述:
在您的服务器上安装有效证书创建 .cer 文件openssl x509 -in www_yourdomain_com.crt -out www_yourdomain_com.cer -outform der
将 .cer 文件添加到应用项目。重要提示:切勿将私钥添加到您的项目中!!!
设置 AFNetworking 安全策略
- (AFSecurityPolicy *)securityPolicy
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
[securityPolicy setAllowInvalidCertificates:NO];
[securityPolicy setValidatesDomainName:YES];
return securityPolicy;
在进行网络调用时设置网络管理器的策略
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager setSecurityPolicy:[self securityPolicy]];
如果您使用policyWithPinningMode:pinningMode
方法创建安全策略,则无需手动加载 .cer 文件,AFNetworking 会自动固定它们。
【讨论】:
感谢您的回复。我不认为这很简单,因为它仍然不起作用。中级证书呢?是否也需要将其连接到 .cer 文件中?我要试试。 ssldecoder.org 对我的证书链很满意,但是当我只是将站点 .crt 转换为 .cer 时,我的应用程序就会崩溃。 它没有用。 AFNetworking 似乎不喜欢证书文件。 使用上述设置时,您是否会收到特定错误或静默失败? 在遍历pinned证书时(有3个),碰到这两行的NSAssert时抛出异常SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data); NSParameterAssert(allowedCertificate);
通过将多个证书添加到安全策略的 pinnedCertificates 数组来固定多个证书: let policy: AFSecurityPolicy = AFSecurityPolicy(pinningMode: AFSSLPinningMode.Certificate) let path: String? = NSBundle.mainBundle().pathForResource("mycert", ofType: "cer") 让 keyData: NSData = NSData(contentsOfFile: path!)! policy.pinnedCertificates = [keyData] 如果您有多个证书,请将它们全部添加:[keyData1, keyData2 etc]以上是关于如何为 AFNetworking 创建 .cer 文件以在 iOS 应用程序包中使用的主要内容,如果未能解决你的问题,请参考以下文章
如何为已弃用的 AFNetworking 2.0 传递授权令牌
AFNetworking - SSL - 添加了 .cer 文件,但在服务器端出现 400 错误
CFNetwork SSLHandshake 因 AFNetworking 2.0、自签名 cer 和 [policy setAllowInvalidCertificates:YES] 而失败
如何为不同的请求方法创建具有不同参数编码的 AFHttpClient?
使用 AFNetworking 进行 SSL 固定 - validatesCertificateChain = true