美文网首页服务端知识
AFNetworking实现HTTPS

AFNetworking实现HTTPS

作者: 优雨 | 来源:发表于2018-01-23 19:22 被阅读98次

    在AFNetworking中,和HTTPS相关的类是AFSecurityPolicy,和其相关的属性和方法主要有以下几个

    1.validatesDomainName

    这个属性声明了客户端是否去验证证书中域名这个字段,默认为YES

    2.allowInvalidCertificates

    这个属性声明了客户端是否信任不可用或者过期的证书,默认为NO

    3.SSLPinningMode

    这个属性声明了客户端如何去校验服务器端给予的证书,默认为AFSSLPinningModeNone

    typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
        AFSSLPinningModeNone,
        AFSSLPinningModePublicKey,
        AFSSLPinningModeCertificate,
    };
    
    • AFSSLPinningModeNone 这个是默认值。当allowInvalidCertificates为YES时,客户端无条件信任服务器返回的证书,否则,会去查询iOS包含的CA根证书列表进行校验。
    • AFSSLPinningModePublicKey 只验证客户端证书中包含的公钥,不验证证书的有效期等信息。
    • AFSSLPinningModeCertificate 不仅验证公钥,也会验证证书本身的有效期等信息

    推荐将这个属性设置为AFSSLPinningModePublicKey,因为如果证书一单过期,就需要手动更新APP进行证书的更新。一般来说,只要公钥正确就能够保证通信是安全的,因为中间人无私钥,无法解开公钥加密的数据,也就无法获取到session key。

    示例:

    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey withPinnedCertificates:cer];
    securityPolicy.validatesDomainName = YES;
    securityPolicy.allowInvalidCertificates = NO;
    self.securityPolicy = securityPolicy;
    

    以上方法对于实现HTTPS来说已经足够了。

    自定义验证

    - (void)setSessionDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block;
    

    AFURLSessionManager提供的setSessionDidReceiveAuthenticationChallengeBlock:方法实际上是对NSURLSessionDelegate的代理方法URLSession:didReceiveChallenge:completionHandler:的封装。当走HTTPS的时候,该代理方法会收到一个challenge(质询),需要你提供认证信息才能完成连接。这时候可以通过 challenge.protectionSpace.authenticationMethod取得保护空间要求我们认证的方式,如果这个值是 NSURLAuthenticationMethodServerTrust的话,我们就可以插手TLS握手中“验证数字证书有效性”这一步。这个方法AFNetworking提供了默认实现,如果我们要自定义验证过程,就需要调用setSessionDidReceiveAuthenticationChallengeBlock:方法来修改。

    evaluateServerTrust:forDomain:

    AFURLSessionManager提供的验证指定的ServerTrust和Domain是否可信任的方法。
    ServerTrust代表服务器的SSL事务状态,可以由challenge.protectionSpace.serverTrust来拿到。

    [self setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession * _Nonnull session, NSURLAuthenticationChallenge * _Nonnull challenge, NSURLCredential *__autoreleasing  _Nullable * _Nullable credential) {
                __strong typeof(weakSelf) strongSelf = weakSelf;
                NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
                if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
                    if ([securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
                        NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                        if (credential) {
                            disposition = NSURLSessionAuthChallengeUseCredential;
                        } else {
                            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
                        }
                    } else {
                        disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
                    }
                } else {
                    disposition = NSURLSessionAuthChallengePerformDefaultHandling;
                }
                //以上调用的是系统默认实现
                if (disposition == NSURLSessionAuthChallengeCancelAuthenticationChallenge) {
                    //证书不可用 自定义验证过程
                    BOOL expired = YES;
                    if (@available(iOS 10, *)) {
                        for (NSData *certData in strongSelf.securityPolicy.pinnedCertificates) {
                            BOOL theExpired = [strongSelf session:session cert:certData didReceiveAuthenticationChallenge:challenge];//验证证书是否全部过期
                            expired = expired && theExpired;
                        }
                    } else {
                        // SecTrustEvaluate 在iOS9 及以下会发生crash,暂停使用
                        expired = NO;
                    }
                    
                    // 证书全部过期,提示升级
                    if (expired) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [strongSelf handleSSLError:handler overdue:YES];
                        });
                    } else {
                        dispatch_async(dispatch_get_main_queue(), ^(void){
                            [strongSelf handleSSLError:handler overdue:NO];
                        });
                    }
                }
                return disposition;
            }];
    

    相关文章

      网友评论

        本文标题:AFNetworking实现HTTPS

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