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))block

4

1 に答える 1

1

私は同じ問題に取り組んでいます.現在、私が見つけたのは、AFNetworkingに関するこの問題といくつかの助けだけです.

基本的にブロックを設定- (void)setTaskDidReceiveAuthenticationChallengeBlock:([long block variable type here])block;しますAFURLSessionManager

証明書は p12 形式で保存されます。次の 2 行で、証明書のファイル名とパスフレーズを変更する必要があります。

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

CFStringRef パスワード = CFSTR("YOURPASSPHRASE");

このブロックを設定するコード全体は次のようになります。

    AFHTTPRequestSerializer *reqSerializer = [AFHTTPRequestSerializer シリアライザー];
    NSMutableURLRequest *リクエスト;
    request = [reqSerializer requestWithMethod:メソッド URLString:[actionURL absoluteString] パラメータ:nil エラー:nil];

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

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer = [AFHTTPResponseSerializer シリアライザー];

    [操作 setSecurityPolicy:securityPolicy];

    [操作 setWillSendRequestForAuthenticationChallengeBlock:^(NSURLConnection *接続、NSURLAuthenticationChallenge *挑戦) {
        if ([前のFailureCountに挑戦] > 0) {
            //これは認証の失敗を引き起こします
            [[チャレンジ送信者] cancelAuthenticationChallenge:チャレンジ];
            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 を取得しました。しかし、他の 2 つは信頼できるサーバーの説明と一致します。
                [challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
                戻る;
            }
        } そうでなければ ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) {
            //これは、クライアント証明書の認証を処理します

            /*
             ここで行う必要があるのは、これを行うために証明書と ID を取得することです。
             NSURLCredential *credential = [NSURLCredential credentialWithIdentity:ID 証明書:myCerts 永続性:NSURLCredentialPersistencePermanent];
             [[チャレンジ送信者] useCredential:credential forAuthenticationChallenge:challenge];

             -installCertificate のコードを使用して、証明書を簡単にロードできます。
             IDを取得することはより困難です。
             .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);

            if(result == 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 永続性:NSURLCredentialPersistencePermanent];
                CFRelease(myCerts);

                [[チャレンジ送信者] useCredential:credential forAuthenticationChallenge:challenge];
            } そうしないと {
                [[チャレンジ送信者] cancelAuthenticationChallenge:チャレンジ];
            }
        } そうでなければ ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault || [[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodNTLM) {

            // ユーザー名とパスワードに基づく通常の認証用。これは、NTLM またはデフォルトの可能性があります。
            /*
             DAVCredentials *cred = _parentSession.credentials;
             NSURLCredential *credential = [NSURLCredential credentialWithUser:cred.username パスワード:cred.password persistence:NSURLCredentialPersistenceForSession];
             [[チャレンジ送信者] useCredential:credential forAuthenticationChallenge:challenge];
             */

            NSLog(@"ベーシック認証");

        } そうしないと {
            //すべて失敗した場合、チャレンジをキャンセルします。
            [[チャレンジ送信者] cancelAuthenticationChallenge:チャレンジ];
        }
    }];

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

        NSLog(@"成功");

    } 失敗:^(AFHTTPRequestOperation *操作、NSError *エラー) {

        NSLog(@"失敗");

    }];

    [[NSOperationQueue mainQueue] addOperation:操作];

このリンクを参照してください: https://github.com/AFNetworking/AFNetworking/issues/2316#issuecomment-115181437

私は今これを試しています。

于 2016-09-19T14:50:27.133 に答える