NSURLConnection - Disable the authentication chall

2019-03-26 05:33发布

问题:

SITUATION

  • Using AFNetworking (NSURLConnection) to access my server API
  • The API needs Basic Authentication with token as username
  • The API returns HTTP 401 when token is invalid
  • I set the Basic Authentication headers before any request
  • If it returns 401, I retry like this:

    AFHTTPRequestOperation *requestOperation = [MyHTTPClient.sharedClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
        processSuccessBlock(operation, responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        processFailureBlock(operation, error);
    
        if (operation.response.statusCode == 401)
            [MyHTTPClient.sharedClient refreshTokenAndRetryOperation:operation success:processSuccessBlock failure:processFailureBlock];
    }];
    

PROBLEM

  • When the server returns HTTP 401 with a Basic Authentication challenge, AFNetworking/NSURLConnection sends the identical request twice (initial request and then in answer to the authentication challenge)
  • But because of the code above that I handle the HTTP 401 myself, this is totally unnecessary and I want it to stop answering the authentication challenge automatically

WHAT I'VE TRIED

  • Responding with cancelAuthenticationChallenge: to willSendRequestForAuthenticationChallenge: is aborting the second call, but it gives the error code -1012 (NSURLErrorUserCancelledAuthentication) instead of 401 and masks the real response

How do you disable the authentication challenge response mechanism so you get the servers response without calling it twice?

回答1:

You have a few of options to fully customize the authentication handling:

  1. Utilize setWillSendRequestForAuthenticationChallengeBlock: and setAuthenticationAgainstProtectionSpaceBlock: from class AFURLConnectionOperation and set corresponding blocks where you can tailor the mechanism you require.

    The headers contain documentation.

  2. Override connection:willSendRequestForAuthenticationChallenge: in a subclass of AFURLConnectionOperation. This will effectively override the complete authentication mechanism setup in AFNetworking.

Note, that you cannot disable the "server validates client identity" authentication challenge -- this is part of the server. You MUST provide the correct credentials for the requested authentication method.



回答2:

Try this.

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    SecTrustRef trust = challenge.protectionSpace.serverTrust;
    NSURLCredential *cred;
    cred = [NSURLCredential credentialForTrust:trust];
    [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
}