Аутентификация AFNetworking NTLM?


Я бьюсь головой, пытаясь заставить AFNetworking работать, так как это мое первое приложение, которое имело дело с клиентом/сервером, где я пытаюсь захватить JSON с HTTPS-сервера, который требует имя пользователя/пароль. Я немного подключил его к приложению, но он продолжает выдавать ошибку 401, которую я искал, чтобы быть основной проблемой аутентификации.

Я в основном взял пример twitter из AFNetworking и адаптировал его к своему проекту. В подклассе AFHTTPClient я добавляю: еще одна строка в initWithBaseURL, и она по-прежнему выдает ошибку. Строка, которую я добавляю, - это 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;
}
2 3

2 ответа:

Если вы пытаетесь использовать аутентификацию NTLM с AFNetworking, вы можете попробовать следующее:

AFNetworking поддерживает аутентификацию NTLM (или в основном любой метод аутентификации), предоставляя блочный ответ на проблемы аутентификации в целом.

Вот пример кода (предполагая, что operation является AFHTTPRequestOperation, AFJSONRequestOperation и т.д.). Перед началом операции установите блок проверки подлинности следующим образом:

[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];
   }
}];

Запустить или поставить в очередь операцию, как обычно, и что это должно сработать.

Это в основном метод, который Уэйн Хартман описывает в своем блоге применительно к AFNetworking.

Я не смог найти метод setAuthenticationChallengeBlock:, упомянутый владельцем принятого ответа (может быть, он был удален с более новой версией?) однако я придумал неблочное решение для аутентификации NTLM, как показано ниже. (На самом деле он написан на Swift, но это не должно быть проблемой, чтобы преобразовать его в Objective C) Вы просто устанавливаете объект учетных данных в вашем экземпляре AFHTTPRequestOperation:

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