AFNetworking NTLM Authentication?

2019-01-20 03:04发布

问题:

I am banging my head trying to get AFNetworking to work since this is my first app that had to deal with Client/Server where I am trying to grab the JSON from a HTTPS server that requires a username/password. I got it somewhat hooked up to the app, but it keeps throwing a 401 Error which I looked it up to be Basic Authentication issue.

I basically took the twitter example from AFNetworking and adapted it to my project. In the subclass of the AFHTTPClient, I am adding another line in the initWithBaseURL and it still throws the error. The line I am adding is the setAuthorizationHeaderWithUsername

- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (!self) {
    return nil;
}

[self registerHTTPOperationClass:[AFJSONRequestOperation class]];

// Accept HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
[self setDefaultHeader:@"Accept" value:@"application/json"];
[self setAuthorizationHeaderWithUsername:@"myusername" password:@"my password"];

return self;
}

回答1:

If you're trying to use NTLM authentication with AFNetworking you could try the following:

AFNetworking does support NTLM authentication (or basically any authentication method) by providing a block-based response to authentication challenges in general.

Here's a code example (assuming operation is a AFHTTPRequestOperation, AFJSONRequestOperation etc.). Before starting the operation set the authentication challenge block like this:

[operation setAuthenticationChallengeBlock:
 ^( NSURLConnection* connection, NSURLAuthenticationChallenge* challenge )
{
   if( [[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodNTLM )
   {
      if( [challenge previousFailureCount] > 0 )
      {
         // Avoid too many failed authentication attempts which could lock out the user
         [[challenge sender] cancelAuthenticationChallenge:challenge];
      }
      else
      {
         [[challenge sender] useCredential:[NSURLCredential credentialWithUser:@"username" password:@"password" persistence:NSURLCredentialPersistenceForSession] forAuthenticationChallenge:challenge];
      }
   }
   else
   {
      // Authenticate in other ways than NTLM if desired or cancel the auth like this:
      [[challenge sender] cancelAuthenticationChallenge:challenge];
   }
}];

Start or enqueue the operation as usual and that should do the trick.

This is basically the method Wayne Hartman describes in his blog applied to AFNetworking.



回答2:

I couldn't find the setAuthenticationChallengeBlock: method mentioned by the owner of the accepted answer (maybe it was removed with a newer version?) however, I came up with the non-block-based solution for NTLM authentication, as shown below. (It is written in Swift actually, but it should not be an issue to convert it to Objective C) You just set your credentials object in your AFHTTPRequestOperation instance:

var reqSerializer:AFHTTPRequestSerializer = AFHTTPRequestSerializer()
var request = reqSerializer.requestWithMethod("GET", URLString: "<URL>", parameters: nil, error: nil)  
var oper = AFHTTPRequestOperation(request: request)

var respSerializer = AFXMLParserResponseSerializer()
oper.responseSerializer = respSerializer

var creds:NSURLCredential = NSURLCredential(user: "<DOMAIN\\USER>", password: "<PASSWORD>", persistence: NSURLCredentialPersistence.None)
oper.credential = creds

oper.setCompletionBlockWithSuccess({ (oper:AFHTTPRequestOperation!, obj:AnyObject!) -> Void in
        //handle success

    }, failure: { (oper:AFHTTPRequestOperation!, err:NSError!) -> Void in
        //handle failure
})

oper.start()