本文主要讲解我们最常用的NSURLConnection支持HTTPS的实现(NSURLSession的实现方法类似,只是要求授权证明的回调不一样而已),以及怎么样使用AFNetworking这个非常流行的第三方库来支持HTTPS。本文假设你对HTTP以及NSURLConnection的接口有了足够的了解。
使用NSURLConnection支持HTTPS的实现
// Now start the connectionNSURL*httpsURL=[NSURL URLWithString:@”https://www.trustauth.cn”];self.connection=[NSURLConnection connectionWithRequest:[NSURLRequestrequestWithURL:httpsURL] delegate:self]; //回调-(void)connection:(NSURLConnection*)connectionwillSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge{ //1)获取trust object SecTrustRef trust=challenge.protectionSpace.serverTrust; SecTrustResultType result; //2)SecTrustEvaluate对trust进行验证 OSStatus status=SecTrustEvaluate(trust,&result); if(status==errSecSuccess && (result==kSecTrustResultProceed || result==kSecTrustResultUnspecified)){ //3)验证成功,生成NSURLCredential凭证cred,告知challenge的sender使用这个凭证来继续连接 NSURLCredential*cred=[NSURL CredentialcredentialForTrust:trust]; [challenge.sender useCredential:cred forAuthenticationChallenge:challenge]; }else{ //5)验证失败,取消这次验证流程 [challenge.sender cancelAuthenticationChallenge:challenge]; }} |
上面是代码是通过系统默认验证流程来验证证书的。但是如何确认服务器返回的证书就是我们想要的特定证书?这就需要先在本地导入证书,设置成需要参与验证的Anchor Certificate(锚点证书,通过SecTrustSetAnchorCertificates设置了参与校验锚点证书之后,假如验证的数字证书是这个锚点证书的子节点,即验证的数字证书是由锚点证书对应CA或子CA签发的,或是该证书本身,则信任该证书),再调用SecTrustEvaluate来验证。
代码如下
//先导入证书NSString*cerPath=…;//证书的路径NSData*cerData=[NSDatadataWithContentsOfFile:cerPath];SecCertificateRef certificate=SecCertificateCreateWithData(NULL,(__bridgeCFDataRef)(cerData));self.trustedCertificates=@[CFBridgingRelease(certificate)]; //回调-(void)connection:(NSURLConnection*)connectionwillSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge{ //1)获取trust object SecTrustRef trust=challenge.protectionSpace.serverTrust; SecTrustResultType result; //注意:这里将之前导入的证书设置成下面验证的Trust Object的anchor certificate SecTrustSetAnchorCertificates(trust,(__bridgeCFArrayRef)self.trustedCertificates); //2)SecTrustEvaluate会查找前面SecTrustSetAnchorCertificates设置的证书或者系统默认提供的证书,对trust进行验证 OSStatus status=SecTrustEvaluate(trust,&result); if(status==errSecSuccess && (result==kSecTrustResultProceed || result==kSecTrustResultUnspecified)){ //3)验证成功,生成NSURLCredential凭证cred,告知challenge的sender使用这个凭证来继续连接 NSURLCredential*cred=[NSURLCredentialcredentialForTrust:trust]; [challenge.senderuseCredential:cred forAuthenticationChallenge:challenge]; }else{ //5)验证失败,取消这次验证流程 [challenge.sendercancelAuthenticationChallenge:challenge]; }} |
建议采用本地导入证书的方式验证证书,来保证足够的安全性。更多的验证方法,请查看官方文档《HTTPS Server Trust Evaluation》
使用AFNetworking来支持HTTPS
AFNetworking是iOS/OSX开发最流行的第三方开源库之一, AFNetworking 的安全相关设定放在AFSecurityPolicy。
AFNetworking定义了三种 ssl pinningmode:
AFSSLPinningModeNone: 代表客户端无条件地信任服务器端返回的证书
AFSSLPinningModePublicKey : 代表客户端会将服务器端返回的证书与本地保存的证书PublicKey的部分进行校验;如果正确,才继续进行。
AFSSLPinningModeCertificate: 代表客户端会将服务器端返回的证书和本地保存的证书中的所有内容,包括PublicKey和证书部分,全部进行校验;如果正确,才继续进行。
(关于 pinning mode:简单的说就是你可以将SSL证书跟你的 APP 一起打包,藉由此机制来避免中间人伪造SSL证书的风险。)
以更加安全的AFSSLPinningModeCertificate验证模式为例。
// 1.获得请求管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // 2.加上这个函数,https ssl 验证。 [manager setSecurityPolicy:[self customSecurityPolicy]]; // https ssl 验证函数 – (AFSecurityPolicy *)customSecurityPolicy { // 先导入证书 NSString *cerPath = [[NSBundle mainBundle] pathForResource:@”xxx” ofType:@”cer”];//证书的路径 NSData *cerData = [NSData dataWithContentsOfFile:cerPath]; // AFSSLPinningModeCertificate 使用证书验证模式 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; // allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO //validatesDomainName 是否需要验证域名,默认为YES; //validatesCertificateChain 是否验证整个证书链,默认为YES; |
GDCA致力于网络信息安全,已通过WebTrust 的国际认证,是全球可信任的证书签发机构。GDCA专业技术团队将根据用户具体情况为其提供最优的产品选择建议,并针对不同的应用或服务器要求提供专业对应的HTTPS解决方案。
GDCA一直以“构建网络信任体系,服务现代数字生活”的宗旨,致力于提供全球化的数字证书认证服务。其自主品牌——信鉴易 TrustAUTH SSL证书:包括 OVSSL、EVSSL、代码签名证书等。为涉足互联网的企业打造更安全的生态环境,建立更具公信力的企业网站形象。