美文网首页iOS收藏iOS进阶iOS
iOS开发HTTPS实现之信任SSL证书和自签名证书

iOS开发HTTPS实现之信任SSL证书和自签名证书

作者: 无忌不悔 | 来源:发表于2016-08-22 18:05 被阅读46635次
    Apple ATS

    首先来分析一下什么是HTTPS以及了解HTTPS对于iOS开发者的意义

    HTTPS 以及SSL/TSL

    • 什么是SSL?

    SSL(Secure Sockets Layer, 安全套接字层),因为原先互联网上使用的 HTTP 协议是明文的,存在很多缺点,比如传输内容会被偷窥(嗅探)和篡改。 SSL 协议的作用就是在传输层对网络连接进行加密。

    • 何为TLS?

    到了1999年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS(Transport Layer Security,传输层安全协议)。SSL与TLS可以视作同一个东西的不同阶段

    • HTTPS

    简单来说,HTTPS = HTTP + SSL/TLS, 也就是 HTTP over SSL 或 HTTP over TLS,这是后面加 S 的由来 。

    HTTPS和HTTP异同:HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。HTTP的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。

    在WWDC 2016开发者大会上,苹果宣布了一个最后期限:到2017年1月1日 App Store中的所有应用都必须启用 App Transport Security安全功能。App Transport Security(ATS)是苹果在iOS 9中引入的一项隐私保护功能,屏蔽明文HTTP资源加载,连接必须经过更安全的HTTPS。苹果目前允许开发者暂时可以继续使用HTTP连接,但到年底所有官方商店的应用都必须强制性使用ATS。

    以下是开发者网站公告原文:

    应用传输安全协议是与iOS9和OS X 10.11一同发布的,该协议需要应用程序通过HTTPS使用安全的网络连接,以提高用户的数据和隐私安全。
    在2016年WWDC上我们宣布在今年年底之前,提交到App Store的应用程序必须支持应用传输安全协议。为了给你们额外的时间去准备,这个截止日期已被延长,当新的截止日期确定的时候,我们将及时提供相关信息。

    2016年12月21日苹果更新了截止日期,宣布延期执行ATS支持要求Supporting App Transport Security

    开发者网站截图

    ** 此举为开发者提供了更多时间来做适配和支持。然而,对于iOS开发者来说,尽早解决HTTPS请求的问题仍为上策。**

    苹果ATS对HTTPS证书的要求

    启用ATS必须符合以下标准,不满足条件的HTTPS证书,ATS都会拒绝连接:

    • 服务器所有的连接使用TLS1.2以上版本
    • HTTPS证书必须使用SHA256以上哈希算法签名
    • HTTPS证书必须使用RSA 2048位或ECC 256位以上公钥算法
    • 使用前向加密技术

    此外,苹果ATS支持CT证书透明,要求开发者使用支持CT证书透明度的SSL证书,确保SSL证书合法透明,防止中间人攻击。

    发送HTTPS请求信任SSL证书和自签名证书,分为三种情况

    1.如果你的app服务端安装的是SLL颁发的CA,可以使用系统方法直接实现信任SSL证书,关于Apple对SSL证书的要求请参考:苹果官方文档CertKeyTrustProgGuide

    这种方式不需要在Bundle中引入CA文件,可以交给系统去判断服务器端的证书是不是SSL证书,验证过程也不需要我们去具体实现。
    示例代码:

    
        NSURL *URL = [NSURL URLWithString:URLString];
        NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
        //创建同步连接
        NSError *error = nil;
        NSData *receivedData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
        NSString *receivedInfo = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
    

    当然,如果你需要同时信任SSL证书和自签名证书的话还是需要在代码中实现CA的验证,这种情况在后面会提到。

    2.基于AFNetWorking的SSL特定服务器证书信任处理,重写AFNetWorking的customSecurityPolicy方法,这里我创建了一个HttpRequest类,分别对GET和POST方法进行了封装,以GET方法为例:

    
    
    + (void)get:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure {
        // 1.获得请求管理者
        AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
        // 2.申明返回的结果是text/html类型
        mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
        // 3.设置超时时间为10s
        mgr.requestSerializer.timeoutInterval = 10;
        
        // 加上这行代码,https ssl 验证。
        if(openHttpsSSL) {
            [mgr setSecurityPolicy:[self customSecurityPolicy]];
        }
        
        // 4.发送GET请求
        [mgr GET:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObj){
            if (success) {
                success(responseObj);
            }
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            if (error) {
                failure(error);
            }
        }];
    }
    
    + (AFSecurityPolicy*)customSecurityPolicy {
        // /先导入证书
        NSString *cerPath = [[NSBundle mainBundle] pathForResource:certificate ofType:@"cer"];//证书的路径
        NSData *certData = [NSData dataWithContentsOfFile:cerPath];
        
        // AFSSLPinningModeCertificate 使用证书验证模式
        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 = NO;
        
        securityPolicy.pinnedCertificates = @[certData];
        
        return securityPolicy;
    }
    
    
    

    其中的cerPath就是app bundle中证书路径,certificate为证书名称的宏,仅支持cer格式,securityPolicy的相关配置尤为重要,请仔细阅读customSecurityPolicy方法并根据实际情况设置其属性。

    这样,就能够在AFNetWorking的基础上使用HTTPS协议访问特定服务器,但是不能信任根证书的CA文件,因此这种方式存在风险,读取pinnedCertificates中的证书数组的时候有可能失败,如果证书不符合,certData就会为nil。

    3.更改系统方法,发送异步NSURLConnection请求。

    
    
    - (void)getDataWithURLRequest {
        //connection
        NSString *urlStr = @"https://developer.apple.com/cn/";
        NSURL *url = [NSURL URLWithString:urlStr];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
        NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
        [connection start];
    }
    

    重点在于处理NSURLConnection的didReceiveAuthenticationChallenge代理方法,对CA文件进行验证,并建立信任连接。

    
    - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
        
        return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
        
     /*
        //直接验证服务器是否被认证(serverTrust),这种方式直接忽略证书验证,直接建立连接,但不能过滤其它URL连接,可以理解为一种折衷的处理方式,实际上并不安全,因此不推荐。
        SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
        return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
                      forAuthenticationChallenge: challenge];
         */
        if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust]) {
            do
            {
                SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
                NSCAssert(serverTrust != nil, @"serverTrust is nil");
                if(nil == serverTrust)
                    break; /* failed */
                /**
                 *  导入多张CA证书(Certification Authority,支持SSL证书以及自签名的CA)
                 */
                NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"cloudwin" ofType:@"cer"];//自签名证书
                NSData* caCert = [NSData dataWithContentsOfFile:cerPath];
                
                NSString *cerPath2 = [[NSBundle mainBundle] pathForResource:@"apple" ofType:@"cer"];//SSL证书
                NSData * caCert2 = [NSData dataWithContentsOfFile:cerPath2];
                
                NSCAssert(caCert != nil, @"caCert is nil");
                if(nil == caCert)
                    break; /* failed */
                
                NSCAssert(caCert2 != nil, @"caCert2 is nil");
                if (nil == caCert2) {
                    break;
                }
                
                SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
                NSCAssert(caRef != nil, @"caRef is nil");
                if(nil == caRef)
                    break; /* failed */
                
                SecCertificateRef caRef2 = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert2);
                NSCAssert(caRef2 != nil, @"caRef2 is nil");
                if(nil == caRef2)
                    break; /* failed */
                
                NSArray *caArray = @[(__bridge id)(caRef),(__bridge id)(caRef2)];
            
                NSCAssert(caArray != nil, @"caArray is nil");
                if(nil == caArray)
                    break; /* failed */
                
                OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
                NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
                if(!(errSecSuccess == status))
                    break; /* failed */
                
                SecTrustResultType result = -1;
                status = SecTrustEvaluate(serverTrust, &result);
                if(!(errSecSuccess == status))
                    break; /* failed */
                NSLog(@"stutas:%d",(int)status);
                NSLog(@"Result: %d", result);
                
                BOOL allowConnect = (result == kSecTrustResultUnspecified) || (result == kSecTrustResultProceed);
                if (allowConnect) {
                    NSLog(@"success");
                }else {
                    NSLog(@"error");
                }
                /* https://developer.apple.com/library/ios/technotes/tn2232/_index.html */
                /* https://developer.apple.com/library/mac/qa/qa1360/_index.html */
                /* kSecTrustResultUnspecified and kSecTrustResultProceed are success */
                if(! allowConnect)
                {
                break; /* failed */
                }
                
    #if 0
                /* Treat kSecTrustResultConfirm and kSecTrustResultRecoverableTrustFailure as success */
                /*   since the user will likely tap-through to see the dancing bunnies */
                if(result == kSecTrustResultDeny || result == kSecTrustResultFatalTrustFailure || result == kSecTrustResultOtherError)
                    break; /* failed to trust cert (good in this case) */
    #endif
                
                // The only good exit point
                return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
                              forAuthenticationChallenge: challenge];
                
            } while(0);
        }
        
        // Bad dog
        return [[challenge sender] cancelAuthenticationChallenge: challenge];
        
    }
    

    这里的关键在于result参数的值,根据官方文档的说明,判断(result == kSecTrustResultUnspecified) || (result == kSecTrustResultProceed)的值,若为1,则该网站的CA被app信任成功,可以建立数据连接,这意味着所有由该CA签发的各个服务器证书都被信任,而访问其它没有被信任的任何网站都会连接失败。该CA文件既可以是SLL也可以是自签名。

    NSURLConnection的其它代理方法实现

    
    #pragma mark -- connect的异步代理方法
    -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
        NSLog(@"请求被响应");
        _mData = [[NSMutableData alloc]init];
    }
    
    -(void)connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)data {
        NSLog(@"开始返回数据片段");
        
        [_mData appendData:data];
    }
    
    -(void)connectionDidFinishLoading:(NSURLConnection *)connection {
        NSLog(@"链接完成");
        //可以在此解析数据
        NSString *receiveInfo = [NSJSONSerialization JSONObjectWithData:self.mData options:NSJSONReadingAllowFragments error:nil];
        NSLog(@"received data:\\\\n%@",self.mData);
        NSLog(@"received info:\\\\n%@",receiveInfo);
    }
    
    //链接出错
    -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
        NSLog(@"error - %@",error);
    }
    

    至此,HTTPS信任证书的问题得以解决,这不仅是为了响应Apple强制性使用ATS的要求,也是为了实际生产环境安全性的考虑,HTTPS是未来的趋势,建议尽早支持。

    如需参考Demo请移步本人在Github上的开源项目

    相关文章

      网友评论

      • 7a946bf5d2ca:afn那个方法无效
        无忌不悔:AFN有更新了,可以自己根据更新的方法替换
      • 南方小金豆:服务器那边的SSL证书过期了,我APP里面加载的证书要怎么办?需要更换嘛?
        无忌不悔:@那份牵挂给了谁 目前还没过期是吗,现在审核快了,可以赶紧弄啊
        南方小金豆:@无忌不悔 这样的话需要强制更新app,有点难搞
        无忌不悔:@那份牵挂给了谁 需要更换吧
      • 即使慢走也不停下:我现在正在搞这个 你写的这个demo 我怎么崩溃了 方便 留一你的联系方式吗? 我的qq 1875998234 微信 673658917 我确实很着急 希望你能帮帮我
        KevinChein:信息暴露了
      • 克里斯star:请问下,NSURLSession要怎么处理?
      • huoku:大神你好,看完你的文章,和下面的评论了,我还是有一点不明白,就是,我现在使用的是AF来进行网络请求的,如果之后使用的证书是SLL颁发的,那么我客户端还需要进行你文章中关于AF的那些修改嘛~
      • gpylove:按这样配了,为啥一直请求返回-999,取消访问
      • 08caf6707801:请问一下,我们公司的是cordova的项目,该如何适配?
      • child_cool:AFSSLPinningModeCertificate 如果设置了这个类型,程序就崩溃,如果设置的是none,程序可以请求到数据,请问这个是什么问题
        无忌不悔:@破小孩儿 关于证书校验,建议参考http://www.jianshu.com/p/4102b817ff2f
      • KeepMoveingOn:内置于app的ca证书会有过期问题,请问博主有没有关于更新ca证书这方面的经验呢?如果过期了会造成已上线版本无法网络请求的问题 :joy:
      • 582da9c9606e:如果是苹果信任的证书,是不是前端就不用配置了,这样的证书在哪能买到....
      • 戀億座郕:你好,最近我们公司有接口需要用HTTPS,但是之前都是用HTTP也就是AF这个网络请求封装类,我没有用过HTTPS,想问一下如何使用HTTPS替换之前的HTTP呢??
        无忌不悔:@戀億座郕 博客和demo中都有
      • MrFanRG:问你了问题,我用你上面的方法一直报NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)这个错误是怎么回事,急急急
        真的在听吗:@ios码农学生 不影响就不要紧 这个是后台加密算法版本太老的原因,建议后台加密更新加密方法
        MrFanRG:@真的在听吗 不崩溃就是一直报NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)这个错误,你说的影像数据是什么意思
        真的在听吗:@ios码农学生 影像数据请求吗? 是否崩溃
      • 6c0f82a95ab7:后台给了一个.crt的证书,怎么加到项目中?
        鹏飞九天324:@6c0f82a95ab7 双击安装到钥匙串中,在钥匙串中右键导出生成cer格式的
      • 真的在听吗:请问 服务器用的是SSL证书 APP端是不需要做什么操作的吧 但是这样显示网络问题啊 请求不到数据 请问是什么原因啊
        无忌不悔:@真的在听吗 没遇到过,应该要转
        真的在听吗:@无忌不悔 后台给的证书是p7b格式的,需要转换格式吗
        无忌不悔:@真的在听吗 请仔细阅读一下博文,按照demo操作,如再有问题再行解决。
      • 道道明明白白:您好,问一下 我们用的是自建的证书,在用webView加载的时候出现了NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802) 这样的问题,请问您是怎么解决的?
        道道明明白白:@无忌不悔 好的 我的QQ: 642294047
        无忌不悔:@道道明明白白 周一你再找我,我们详细找找问题吧
      • 9e951bc4673b:群主你好,我的应用使用企业及账号开发的,公司的接口是http的,苹果的这个强制使用https这个应用有影响吗 :stuck_out_tongue_winking_eye:
      • ITLikeyi:兄弟。 我按你说的 把证书导入 为什么是nil哦
        // /先导入证书
        NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"bus.carles.cn" ofType:@"cer"];//证书的路径
        NSData *certData = [NSData dataWithContentsOfFile:cerPath];
        NSSet *cerSet = [NSSet setWithObject:certData];
        断点过了cerPath 后 显示的是nil 然后就崩溃了 为什么会是nil
        ITLikeyi:@无忌不悔 我配置好证书后 访问http的接口
        直接蹦了
        访问https 就报这个
        NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9806)
        无忌不悔:@ITLikeyi 你确定你的证书文件名叫这个?请看看报错是什么,评论里好像有朋友遇到过
      • 真的在听吗:如果后台把所有都改成HTTPS了 iOS项目里是不是就不用改动了??
        无忌不悔:@真的在听吗 要看你是哪种情况,配的是什么证书
      • 真的在听吗:你好,请问iOS开发项目里必须要做这些操作吗
        无忌不悔:@真的在听吗 您可以根据情况分析
      • f10cfdcc90a3:首先非常感谢你,这个分享太棒了,我是菜鸟想咨询下,我这边用的腾讯云和第三方合作的ssl,服务器端如果配置了,我这边用af请求,如何知道是不是https请求成功了?
      • 介是阿姐:你好,想请教一下,如果我们公司是后台人员自己申请的证书,前端应该按照第几条进行配置,第2条么?并且我的项目是AFN完全没有封装,改起来会不会很麻烦?
        无忌不悔:@邓姑娘 用AFN只需要还的话只需要改里面封装的那部分就行了
        介是阿姐:@无忌不悔 是按照第2条尽行更改么?并且对AFN有过请求的地方全进行更改么?
        无忌不悔:@邓姑娘 是的,需要改一下
      • 知之未道: @无忌不悔 因为项目比较早,用的还是ASI,请问ASI的https怎么设置呢?
        知之未道:@无忌不悔 恩恩,多谢
        无忌不悔:@知之未道 没用过,恕我不知
      • 灰斗儿:苹果官方的ca怎么申请?跟上架用的证书不同?
        无忌不悔:@autorelease 百度一下吧,不是苹果官方,是签发机构
        灰斗儿:@autorelease 怎么买呢 苹果官方的
        无忌不悔:@autorelease 要买的,是HTTPS 的证书,跟开发者证书不同
      • 缭雾:学习了 :smile:
      • 你大赟哥:@无忌不悔 我用afn 然后跟你一样设置,然后 报了baseurl的错误,然后改成AFSSLPinningModeNone 这样。。get是可以用了,但是post却不能用
        你大赟哥:@无忌不悔 postman是可以的 用post没有错 有数据,是不是因为AFSSLPinningModeNone 这个的原因
        无忌不悔:@你大赟哥 没道理只能用GET方法,你找一下原因吧
        你大赟哥:@无忌不悔 Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: not found (404)" UserInfo={com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x600000236860> { URL: https://kyl.api.app.kuakao.com/content/recommend/major-find-school } { status code: 404, headers {
        Date = Thu, 08 Dec 2016 05:18:12 GMT;
        Transfer-Encoding = Identity;
        Content-Type = application/json; charset=UTF-8;
        X-Powered-By = PHP/5.5.30;
        Connection = keep-alive;
        Server = nginx/1.6.0;
        }
      • ITLikeyi:你好,大神。这两天一直在弄https的问题, 看了你的文章受益匪浅,但是有一个问题 想咨询你一下。
        我在什么也没更改的情况下 用nsurlsession访问https接口可以得到数据,所以我怀疑我们的服务器证书是认证的,所以我问了服务器同事 ,他说是在网站上申请的免费的。
        我在浏览器的锁头里找到了我们服务器的证书信息:
        证书名称和签发者:VeriSign Class 3 Public Primary Certification Authority - G5
        并且 我在官方网站的“可信”证书里 找到了 这个签发者。
        1. 那意味着 我们公司的服务器证书 是受信任的SSL证书咯?
        2.是不是就不需要更改什么了?
        3.但是 我查看证书时显示的是128位秘钥,TLS1.0, 请问是否要同事升到1.2?
        本人菜鸟一枚,请大神见谅,坐等回复,谢谢!!!
        无忌不悔:@ITLikeyi 👌🏻
        ITLikeyi:@无忌不悔 晓得了,多谢回复。 :+1:
        无忌不悔:@ITLikeyi 证书有效就不需要再做其他操作,至于证书升级的问题我认为应该交给后端工程师或运维
      • LikeSmilence:请问我想咨询一下,如果使用自制证书可以通过苹果审核吗
        LikeSmilence:@无忌不悔 谢谢。我们公司也制作了一个自制证书。最后审核不过估计就得买了
        无忌不悔:@LikeSmilence 我们有使用自签名证书的app,不过现在还没上线,还不知道苹果会不会限制。还在探索
      • EchoZuo:您好,咨询一下。我现在项目服务器端购买的CA证书。这样的话我在iOS端如何处理?现在情况 是这样,服务器告诉我将接口的http改成http就行,我现在改了之后可以正常访问并且拿到数据了。但是我没有做任何验证。如果是购买的CA证书,iOS端需要验证码?如何验证,现在用的网络类全部是最新版的Afnetworking。。看到后帮我解答一下,非常感谢。
      • f5bfde00b550:请问下 您说"SLL机构颁发的CA证书" 但是没有搜到SLL啊 只有SSL.
        f5bfde00b550:@无忌不悔
      • 2f5eca5dff1c:请问图片的URL和H5的URL必须要改成https吗?
      • huifeidelele:你好,请问下如果证书是CA中心颁布,但是不是受苹果信任的CA中心颁布的证书,是哪种情况?该怎么处理?
      • 3e6d849c459f:1,如果是购买的SSL证书, 服务器配置过后把 cer给客户端导入到bundle后 ,客户端还需要做什么?
        2,如果是自签名的证书, 服务器和客户端都需要做什么工作?
      • cwh11022:如果你的app服务端安装的是SLL颁发的CA,可以使用系统方法直接实现信任SSL证书?
        系统方法直接实现信任SSL证书?这个怎么操作,需要在本地写代码操作吗?还是说导入SSL,点击信任之类的操作?
        无忌不悔:@cwh11022 我在dome中有示例代码,看一下您就明白了
      • 来自蒙塔基的钢蛋儿:你好,我想问一下。我们是购买的SSL证书,按理说我们客户端是不需要验证证书的。但是我用afn3.0,设置server.cer证书,afn SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(cerData)); 这个方法会返回nil 导致程序crash 请问知道是什么原因吗
        最晴天:是哪里的问题?怎么解决的?
        无忌不悔:@来自蒙塔基的钢蛋儿 不知道呢,一直没时间看3.0如果你按照我的方法出错那就是不适配了
      • YearRen:呃…用楼主的demo,导入自签名证书,一直抛异常"caRef is nil" 但是证书放工程中nsdata也有字节SecCertificateCreateWithData 这个转出来总是空是什么意思呢?

        YearRen:@无忌不悔 恩 弄好了 :blush:
        真的在听吗:@YearRen 请问你们签名证书是从哪里得到的
        无忌不悔:@YearRen 请问有没有把证书名替换掉呢,还有我为了说明证书数据对象是一个数组,加入了两张证书,需要去掉一张证书对象。另外请检查你的证书及其格式符不符合要求。
      • 竹寺000:你好,请问你们公司的证书是从哪个机构申请的呢 ?? 我们服务说他从阿里云申请的,是单向证书,只要服务器验证就可以。。这样可以吗 ??
      • EchoZuo:您好,咨询一下,发送HTTPS请求信任SSL证书和自签名证书的第一种情况:
        NSURL *URL = [NSURL URLWithString:URLString];
        NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
        //创建同步连接
        NSError *error = nil;
        NSData *receivedData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
        NSString *receivedInfo = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];

        里面的URL是什么?是什么url?
        无忌不悔:@EchoZuo 是的,试了就知道,文章中有写
        EchoZuo:@无忌不悔 您好,如果是第一种SSL的证书。是不需要在Bundle中引入CA文件,然后iOS的代码也就是正常访问就可以了是吗?然后系统自动去验证?
        无忌不悔:@EchoZuo 是的
      • Wayne_Wang:请问 如果买的证书 前端是不是就不需要处理什么?我们公司买的证书,我用AFN请求没做任何请求处理, iOS10 以上 Allow Arbitrary Loads置为NO 请求 能拿到数据 ,网上我找了些资料 有些人说买的证书不需要处理 但是我又怕 这样 不符合要求 ,请指教!
        无忌不悔:@冷碎音阶丿寒 是这样的,苹果的目的就是这个
        Wayne_Wang:@无忌不悔 谢谢,我没去看那个 我昨天尝试了下 我们公司买的证书 没修改 能拿到数据关闭Allow Arbitrary Loads 跑10.0也可以 看来花钱还是有用的。嘿嘿
        无忌不悔:@冷碎音阶丿寒 有SSL证书不需要处理的,你可以查看苹果官方证书列表
      • 青空逸隐: @无忌不悔 哦, 谢谢你的回复. 另外我仍然还有所疑惑需要问下; 需求是实现双向验证; 目前我项目中导入服务器给的证书进行验证,使用AFN3.1做请求,AFSecurityPolicy 部分该如何配置?
        NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"sever" ofType:@"cer"];
        NSData *certData = [NSData dataWithContentsOfFile:cerPath];
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
        securityPolicy.allowInvalidCertificates = YES;
        securityPolicy.validatesDomainName = NO;
        这样做可行吗,能否达到验证服务器证书的合法性?
        另外info.plist是否还需要对ATS做配置?
        无忌不悔:@書冩傳奇 基于你们的SSL证书应该设置securityPolicy.allowInvalidCertificates = NO;AFN需要对ATS进行配置,系统方法应该不需要。
        青空逸隐:@无忌不悔 嗯,断点时,看到这整段code有走,但不清楚其间功能的是否实现
        问下AFN3.0之前
        securityPolicy.allowInvalidCertificates = YES;
        securityPolicy.validatesDomainName = NO;
        这样配置是否能达到验证效果
        项目中info.plist这些是否需要对ATS做配置?
        无忌不悔:@書冩傳奇 AFN3.0改动比较大我还没有试过,你可以尝试一下只修改securityPolicy方法,然后下断点查看验证过程是否完整有效
      • CaesarsTesla:你们的HTTPS证书,是从哪买的?
        CaesarsTesla:@无忌不悔 嗯嗯,是有挺多,正在比较呢,也想看看别人家都用的什么
        无忌不悔:@M东永 这个不是很清楚,去网上应该好找渠道,找那些做这方面服务的官网。
      • ZIM东东:那后台开发不用真的证书行么,贵啊,做个伪的HTTPS站行么;审核能通过么,我们正要做,但是不知道伪站可以么,我这提交的iOS几个app都还是http
        ZIM东东:@无忌不悔 谢谢,
        无忌不悔:@badBoys 这个我也目前不清楚,苹果的规定目前只是要支持HTTPS,没对HTTPS作具体要求,建议你们多评估一下,还可以向苹果客服咨询。
      • 7bb125327537:你好!感谢你写这篇文章帮助我们刚接触https的新手,但是文章中有一个地方不太明白:基于AFNetWorking的SSL特定服务器证书信任处理,重写AFNetWorking的customSecurityPolicy方法,在这个方法中你有导入了证书(我理解为这个是自签名证书),那这个地方就不是AFNetWorking的SSL特定服务器证书信任处理啊!不知道我是不是哪里理解错了,望指教,谢谢!
        无忌不悔:@7bb125327537 你好,这里既可以是自签名证书也可以是SSL证书。自签名证书需要设置allowInvalidCertificates为YES,个人认为这个版本的AFNetworking对HTPPS的支持不是很好,在我的尝试中遇到过一些很奇怪的问题,可能还需要完善和研究,能实现和有效的方法我在本文中提供给大家参考,AF在不断更新,我也会尽量根据其更新跟进研究,如果有进展将会在这里分享给大家,谢谢!
      • 含泪若笑:问一下 https证书失效了,可以忽略吗?
        无忌不悔:@hanleirx 忽略验证暂时可以,但是达不到效果,这种途径就是不管证书是什么,只要有证书,是HTTPS的就通过验证,不经过验证
        含泪若笑:@无忌不悔 就是不能忽略是吗
        无忌不悔:@hanleirx 失效了会受影响的
      • 开发仔小广:服务器人员问我需要双向证书还是单向证书,我菜鸟,懵逼了,求大神回答
        无忌不悔:@書冩傳奇 app端可以选择直接交给系统方法去验证,也可以在程序中针对服务器证书进行验证
        青空逸隐:@无忌不悔 问下如果是双向的话,服务器有购买 SLL颁发的CA证书;那么app端还需要做些什么操作?
        无忌不悔:@XG小广 双向
      • 神采飞扬_2015:弱弱问一下,SLL颁发的CA这个是免费的还是收费?
        无忌不悔:@N 是的,苹果对那些SSL 证书是认的
        f123d21a3107:@无忌不悔 用这个证书是不是iOS端就什么不用处理了?我这试了试什么都不改,HTTPS请求就是正常的
        无忌不悔:@神采飞扬_2015 收费,很贵
      • 神采飞扬_2015:有两个问题,1、我现在客户端的接口请求配置了证书,接口请求数据已加密是OK的,但是之前通过链接打开的网页却打不开了,这个怎样处理?2、假如我现在需要多个域名进行接口请求数据,这个如何处理?
        无忌不悔:@神采飞扬_2015 第三个域名的证书和其他的处理方式一样吗,你可以根据官方我当看相应的错误代码是什么错误
        神采飞扬_2015:@无忌不悔 现在有一个问题: <key>NSAppTransportSecurity</key>
        <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSExceptionDomains</key>
        <dict>
        <key>webapitest.bbs.szhome.com</key>
        <dict>
        <key>NSExceptionAllowsInsecureHTTPLoads</key>
        <false/>
        </dict>
        <key>webapi.bbs.szhome.com</key>
        <dict>
        <key>NSExceptionAllowsInsecureHTTPLoads</key>
        <false/>
        </dict>
        <key>deeplink.app.szhome.com</key>
        <dict>
        <key>NSExceptionAllowsInsecureHTTPLoads</key>
        <false/>
        </dict>
        </dict>
        </dict>

        通过第三个域名调用接口返回错误:Error Domain=kCFErrorDomainCFNetwork Code=310 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2096, _kCFStreamErrorDomainKey=4} 这是什么情况?如果我把第三个域名的配置注释掉,调用接口OK,数据也已经加密。
        无忌不悔:@神采飞扬_2015 抱歉,最近比较忙没有回复。对于第一个问题,不知道你们抓包测试是否正常?第二个问题,证书的对象是一个数组,因此可以针对多个域名信任多个证书。
      • lee_zhou:你好,我想请问下,如果用自签名的证书,AppStore审核会被拒绝吗?谁有类似的经验。
        lee_zhou:@无忌不悔 非常感谢回复
        无忌不悔:@lee_zhou 这个没有试过,最好用认证证书
      • FongG:您好,请问能发布一个使用AFNetworking做https请求的demo吗
        无忌不悔:@Jin_先生 你好,我在本文的第2点(基于AFNetWorking的SSL特定服务器证书信任处理)中写到过AFNetWorking信任证书的用法,只需要重写AFNetWorking的customSecurityPolicy方法即可,在代码中相应的地方指向你的证书文件就可以了
        FongG:@无忌不悔 能够细说一下AF会碰到哪些问题吗 :pray:
        无忌不悔:@Jin_先生 AF的之前用过,后来发现问题就用系统方法了
      • EmilyLZJ:你好 请问如果进行https请求的话,前端都需要验证SSL证书吗
        无忌不悔:@Summday 前端不需要,但是后端提供给iOS客户端的代码必须支持HTTPS
      • 张三疯疯子:请问作者,我这边后台哥们给了我两个证书, 一个是cer格式的, 还有一个是bks格式的,我要怎么处理
        无忌不悔:@张三疯疯子 用cer格式的应该可以,还要验证一下证书的类型和可用性。
      • 863c73f31933:您好,问一下,在把交给系统去判断服务器端的证书是不是SSL证书时,能不能知道系统校验的证书是我们钥匙串中的那个证书,还有能不能在钥匙串中临时禁用该证书,已验证正确性。
        无忌不悔:@SunlightInMyLif 你需要问一样你们后台根证书是哪一个,禁用本机钥匙串中的证书起不到作用啊,如果是打包在程序中的证书,可以一个个试一下,另外证书文件中也是有说明的,你可以看出来它的域名和适用范围。
        863c73f31933:@无忌不悔 证书是放到钥匙串中,但是我怎么知道我这个程序中用https需要的根证书是那个,有什么方式那把系统的某一个根证书临时禁用一下,之后再打开,以便于验证和找出我这边使用的证书到底钥匙串中的那一个证书么?
        无忌不悔:@SunlightInMyLif 不是很清楚您讲的情形,证书在钥匙串中的管理是一样的,但是这里最重要的是服务器上的证书,至于具体情况可以测试一下
      • 机器猫的百宝袋:请问:
        ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
        request.timeOutSeconds = 50;
        NSData *cerFile = [NSData dataWithContentsOfFile:[[NSBundle bundleForClass:self.class] pathForResource:@"ca" ofType:@"crt"]];
        SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)cerFile);
        NSArray *array = [NSArray arrayWithObjects:(__bridge id)cert,nil];
        [request setClientCertificates:array];
        [request setValidatesSecureCertificate:NO];


        这样集成crt文件到asi,只有这句[request setValidatesSecureCertificate:NO];起到关键作用了,如果注释该句,还是无法 hand shake failed。
        无忌不悔:@机器猫的百宝袋 正如我在注释中提到:这个值一般情况下需要设为YES,但如果你的服务器地址的域名是否和app中的域名一致,如果你的证书是*.company.com的话是不会发生这种问题。
      • 73d928a3a8be:hello,问下cer证书是怎么获取的?服务器给的吗?
        无忌不悔:@嘛哒哒呦 好的,有任何问题可以在评论中交流或者在github上提交issue。
        73d928a3a8be:@无忌不悔 我先试试
        无忌不悔:@嘛哒哒呦 是的,保持跟服务器端的证书文件一致就可以了,如果是自签名证书直接找后台要他们生成的CA文件,可能不一定是.cer文件。

      本文标题:iOS开发HTTPS实现之信任SSL证书和自签名证书

      本文链接:https://www.haomeiwen.com/subject/jgrgsttx.html