How to use AFNetworking 2 with Digest Authentication

北城余情 提交于 2021-02-07 14:40:41

问题


I've been searching for "AFNetworking 2 with Digest Authentication" for a while and haven't found useful discussions about it (except this one, but unfortunately it looks like it's for AFNetworking 1).

Here's my code without authentication:

NSString* apiURL = @"https://api.example.com/WS.asmx";
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager
    GET:apiURL 
    parameters: [NSDictionary dictionaryWithObjectsAndKeys:@"ID", 1234 , nil]
    success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"JSON: %@", responseObject);
    }
    failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"WS request failed: %@", error);
    }
];

Where and how can Digest Auth code kick in?


回答1:


This question is a bit old, but I had to do just this and I couldn't find any built in way to handle it. The solution I used was to edit AFNetworkings AFURLSessionManager.m. Basically you modify this delegate method to support http digest, heres a full example.

    - (void)URLSession:(NSURLSession *)session
                  task:(NSURLSessionTask *)task
    didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
     completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
    {
        NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        __block NSURLCredential *credential = nil;

        if (self.taskDidReceiveAuthenticationChallenge) {
            disposition = self.taskDidReceiveAuthenticationChallenge(session, task, challenge, &credential);
        } else {
            if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
                if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
                    disposition = NSURLSessionAuthChallengeUseCredential;
                    credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                } else {
                    disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
                }
            } else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest]) {
                NSDictionary *userkeys = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:challenge.protectionSpace];

                credential = [userkeys objectForKey:(NSString *)[[userkeys allKeys] objectAtIndex: 0]];
                if (credential) {
                    disposition = NSURLSessionAuthChallengeUseCredential;
                } else {
                    disposition = NSURLSessionAuthChallengePerformDefaultHandling;
                }
            }else {
                disposition = NSURLSessionAuthChallengePerformDefaultHandling;
            }
        }

        if (completionHandler) {
            completionHandler(disposition, credential);
        }
    }

You will need to add a credential to the sharedCredentialStorage before this challenge. You can check the apple docs for that as it is fairly straight forward but make sure the protection space matches up exactly, including the realm. I hope it helps someone.




回答2:


I recently upgrade to AFNetworking-3, there's no NSURLConnection support anymore.

When I change to NSURLSession, I got same problem.

Thank you bob, edit AFNetworkings AFURLSessionManager.m works fine for me.

But after that, I found a easier way if self.taskDidReceiveAuthenticationChallenge is set, we don't have to change AFNetworkings code.

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

NSURLCredential *myCredential = [[NSURLCredential alloc] initWithUser:@"username" password:@"password" persistence:NSURLCredentialPersistenceForSession];

[manager setTaskDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession * _Nonnull session, NSURLSessionTask * _Nonnull task, NSURLAuthenticationChallenge * _Nonnull challenge, NSURLCredential *__autoreleasing  _Nullable * _Nullable credential) {
    if (challenge.previousFailureCount == 0) {
        *credential = myCredential;
        return NSURLSessionAuthChallengeUseCredential;
    } else {
        return NSURLSessionAuthChallengePerformDefaultHandling;
    }
}];



回答3:


Took me awhile to figure this out and I didn't see any solutions for AFNetworking 4.0 (4.0 is needed as it removes the deprecated UIWebView which Apple now rejects if found), do this;

NSURLCredential *myCredential = [[NSURLCredential alloc] initWithUser:username password:password persistence:NSURLCredentialPersistenceForSession];

[manager setAuthenticationChallengeHandler:^id _Nonnull(NSURLSession * _Nonnull session, NSURLSessionTask * _Nonnull task, NSURLAuthenticationChallenge * _Nonnull challenge, void (^ _Nonnull completionHandler)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable credential)) {
    if (challenge.previousFailureCount == 0) {
        return myCredential;
    } else {
        return @(NSURLSessionAuthChallengePerformDefaultHandling);
    }
}];



回答4:


I just used the following code and worked fine

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:@"Username" password:@"Password" persistence:NSURLCredentialPersistenceForSession];
[manager setCredential:credential]; 


来源:https://stackoverflow.com/questions/22051250/how-to-use-afnetworking-2-with-digest-authentication

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!