AFNetworking NTLM身份验证?

3
我正在尝试让AFNetworking工作,因为这是我第一个需要处理客户端/服务器的应用程序,我正在尝试从需要用户名/密码的HTTPS服务器中获取JSON。我已经将其与应用程序部分连接起来,但它一直抛出401错误,我查了一下发现是基本身份验证问题。
我基本上采用了AFNetworking中的Twitter示例,并将其适应到我的项目中。在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;
}

我专门使用自定义的基于会话的身份验证方案;但我想知道是否最好通过确保HTTP身份验证与AFNetworking部分分开工作来诊断此问题。有一些OS X应用程序可以让您做到这一点,例如cocoa-rest-client。一旦您确信终端身份验证正在工作,就可以返回处理iOS应用程序中的AFNetworking部分。 - FluffulousChimp
2
我刚刚意识到服务器不支持基本身份验证,而是NTLM...这是否意味着AFNetworking对我的目的无法使用?我对网络编程非常陌生,正在学习中。非常感谢您回复这个帖子! - Alan
2个回答

5
如果您正在尝试使用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];
   }
}];

按照惯例开始或排队操作,这样就可以解决问题。

基本上,这是 Wayne Hartman 在他的博客中描述的方法应用于 AFNetworking


4

我找不到被接受的答案的所有者提到的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()

在这里完美地工作了。而且我正好想用Swift。谢谢! - rsc
嘿,最新的Alamofire和Swift可能有什么答案? - Hemang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接