5

我正在尝试从 AFNetworking 2.0 迁移到 3.0。

在以前的版本中,我将创建一个 AFHTTPRequestOperation 并使用 setWillSendRequestForAuthenticationChallengeBlock 在另一个块中处理客户端 SSL 身份验证。

例如:

[operation setWillSendRequestForAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) {
    if ([challenge previousFailureCount] > 0) {
        //this will cause an authentication failure
        [[challenge sender] cancelAuthenticationChallenge:challenge];
        return;
    }

    //this is checking the server certificate
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {

        SecTrustResultType result;
        //This takes the serverTrust object and checkes it against your keychain
        SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);

有人可以向我展示如何使用 AFHTTPSessionManager 执行此操作的示例吗?

我是否需要改为使用 AFURLSessionManager 发出请求?我确实在那里看到了一个块方法:

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

4

1 回答 1

1

我正在解决同样的问题,目前我发现的只是 AFNetworking 上的这个问题,需要一些帮助。

基本上- (void)setTaskDidReceiveAuthenticationChallengeBlock:([long block variable type here])block;在你的AFURLSessionManager

证书以 p12 格式保存。您需要在这两行中更改证书的文件名和密码:

NSData *p12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cert" ofType:@"p12"]];

CFStringRef 密码 = CFSTR("YOURPASSPHRASE");

设置此块的整个代码如下所示:

    AFHTTPRequestSerializer *reqSerializer = [AFHTTPRequestSerializer 序列化器];
    NSMutableURLRequest *请求;
    request = [reqSerializer requestWithMethod:method URLString:[actionURL absoluteString] 参数:nil error:nil];

    AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
    [securityPolicy setAllowInvalidCertificates:kAllowsInvalidSSLCertificate];

    AFHTTPRequestOperation *操作 = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer = [AFHTTPResponseSerializer 序列化器];

    [操作 setSecurityPolicy:securityPolicy];

    [操作 setWillSendRequestForAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) {
        if ([挑战 previousFailureCount] > 0) {
            //这将导致认证失败
            [[挑战发件人] cancelAuthenticationChallenge:challenge];
            NSLog(@"错误的用户名或密码");
            返回;
        }

        //这是检查服务器证书
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            SecTrustResultType 结果;
            //这需要 serverTrust 对象并根据您的钥匙串检查它
            SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);

            //如果我们想忽略证书的无效服务器,我们只接受服务器
            if (kAllowsInvalidSSLCertificate) {
                [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
                返回;
            } 否则如果(结果 == kSecTrustResultProceed || 结果 == kSecTrustResultUnspecified){
                //当针对受信任的服务器进行测试时,我每次都得到 kSecTrustResultUnspecified。但其他两个匹配受信任服务器的描述
                [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
                返回;
            }
        } else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) {
            //这处理验证客户端证书

            /*
             我们需要在这里做的是获取证书和一个身份,以便我们可以这样做:
             NSURLCredential *credential = [NSURLCredential credentialWithIdentity:身份证书:myCerts 持久性:NSURLCredentialPersistencePermanent];
             [[挑战发件人] useCredential:credential forAuthenticationChallenge:challenge];

             使用 -installCertificate 中的代码很容易加载证书
             更难获得身份。
             我们可以从 .p12 文件中获取它,但您需要一个密码:
             */

            NSData *p12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cert" ofType:@"p12"]];

            CFStringRef 密码 = CFSTR("YOURPASSPHRASE");
            const void *keys[] = { kSecImportExportPassphrase };
            const void *values[] = { 密码 };
            CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, 键, 值, 1, NULL, NULL);
            CFArrayRef p12Items;

            OSStatus 结果 = SecPKCS12Import((__bridge CFDataRef)p12Data, optionsDictionary, &p12Items);

            如果(结果 == noErr){
                CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0);
                SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);

                SecCertificateRef certRef;
                SecIdentityCopyCertificate(identityApp, &certRef);

                SecCertificateRef certArray[1] = { certRef };
                CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
                CFRelease(certRef);

                NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp 证书:(__bridge NSArray *)myCerts persistence:NSURLCredentialPersistencePermanent];
                CFRelease(myCerts);

                [[挑战发件人] useCredential:credential forAuthenticationChallenge:challenge];
            } 别的 {
                [[挑战发件人] cancelAuthenticationChallenge:challenge];
            }
        } else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault || [[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodNTLM) {

            // 用于基于用户名和密码的正常身份验证。这可以是 NTLM 或默认值。
            /*
             DAVCredentials *cred = _parentSession.credentials;
             NSURLCredential *credential = [NSURLCredential credentialWithUser:cred.username password:cred.password persistence:NSURLCredentialPersistenceForSession];
             [[挑战发件人] useCredential:credential forAuthenticationChallenge:challenge];
             */

            NSLog(@"基本认证");

        } 别的 {
            //如果一切都失败了,我们取消挑战。
            [[挑战发件人] cancelAuthenticationChallenge:challenge];
        }
    }];

    [操作 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSLog(@"成功");

    } 失败:^(AFHTTPRequestOperation *操作,NSError *错误){

        NSLog(@"失败");

    }];

    [[NSOperationQueue mainQueue] addOperation:operation];

请参阅此链接:https ://github.com/AFNetworking/AFNetworking/issues/2316#issuecomment-115181437

我现在正在尝试这个。

于 2016-09-19T14:50:27.133 回答