iOS:我如何接收HTTP 401而不是-1012 NSURLErrorUserCancelledAuthentication

时间:2010-10-12 07:47:32

标签: iphone http ios nsurlconnection

我遇到的问题类似于以下链接中描述的问题。

NSHTTPURLResponse statusCode is returning zero when it should be 401

我使用[NSURLConnection sendSynchronousRequest:returningResponse:error:]从服务器获取数据。

当NSURLConnection收到HTTP代码401时,它不会从NSURLErrorDomain返回任何代码为-1012的错误对象。 -1012对应NSURLErrorUserCancelledAuthentication。由于我必须解析HTTP Header,我需要获取原始错误而不是NSURLConnection所做的。

有没有办法接收原来的401 http数据包?

5 个答案:

答案 0 :(得分:19)

是。停止使用同步API。如果您使用基于异步委托的API,那么您可以更好地控制连接。使用此API,除非在收到HTTP标头之前遇到错误,您将始终接收-connection:didReceiveResponse:,这使您可以访问HTTP标头字段(封装在{ {1}}对象)。如果您愿意,也可以使用相关的委托方法实现身份验证。

答案 1 :(得分:18)

解决方法:

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue new] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

NSHTTPURLResponse *aResponse = (NSHTTPURLResponse *)response;
int statusCodeResponse = aResponse.statusCode;

NSString *strError = [NSString stringWithFormat:@"%@", [connectionError description]];
if ([strError rangeOfString:@"Code=-1012"].location != NSNotFound) {
    statusCodeResponse = 401;
   }

不是最好的解决方案,但它有效!

答案 2 :(得分:11)

我对#34;推荐"感到惊讶。回答这个帖子。

很好,我确定更好地使用异步版本方法 ,但它仍然无法解释为什么sendSynchronousRequest函数允许您传入变量返回响应代码,但在某些情况下,它只返回 nil

它' 4年自从这个问题被报道以来,我使用XCode 6.2和iOS 8.2,这个古老的bug仍然存在。

当用户的用户名和用户名时,我的网络服务故意返回401错误密码不正确。

当我的iPhone应用程序调用此服务时(使用错误的凭据)...

NSHTTPURLResponse *response = nil;
NSData *data = [ NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error ];

.. response以nil的形式返回(因此我无法测试HTTP响应401),error收到包含的-1012消息这个:

    Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" 
    UserInfo=0x174869940 {NSErrorFailingURLStringKey=https://mywebservice.com/Service1.svc/getGroupInfo/6079, NSUnderlyingError=0x174e46030 
    "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1012.)",
NSErrorFailingURLKey=https://mywebservice.com/Service1.svc/getGroupInfo/6079}

并且sendSynchronousRequest函数返回一个冗长的XML字符串,其中包含...... well ... this ...

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Request Error</title>
    <style>BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;}</style>
  </head>
  <body>
    <div id="content">
      <p class="heading1">Request Error</p>
      <p>The server encountered an error processing the request. The exception message is 'Access is denied.'. See server logs for more details. The exception stack trace is: </p>
      <p>   at System.ServiceModel.Dispatcher.AuthorizationBehavior.Authorize(MessageRpc&amp; rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</p>
    </div>
  </body>
</html>

来吧Apple,修复你的错误......

答案 3 :(得分:0)

它实际上很简单。现在确实异步请求实际上是一个非常好的帮手。但你必须记住它只是一个帮手。 Http只是一个用于网络的协议,因此它不能与用户交互。换句话说,这两种情况实际上是同一个。

如果您不想使用asynch帮助程序而不是我建议您向用户显示登录对话框并重复您的请求,直到用户按下取消。

[编辑]

仅供参考,我个人更喜欢卷曲。几乎到处都像魅力一样;)

答案 4 :(得分:0)

我面临的问题是没有收到401 Unauthorized错误代码(得到nil响应,而且还没有调用didReceiveResponse方法)而是收到-999取消错误。我在代码中犯的错误是: 在didReceiveChallenge中:委托方法,

if (challenge.previousFailureCount == 0)
{
    //handle certificate trust
    completionHandler (NSURLSessionAuthChallengeUseCredential, newCredential);
}
else
{
    completionHandler (NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}

NSURLSessionAuthChallengeCancelAuthenticationChallenge导致-999错误,并且没有获得401响应。 相反,当我使用completionHandler(NSURLSessionAuthChallengePerformDefaultHandling,nil)时;我在didReceiveResponse中接收了401响应:委托方法如预期的那样。

来自iOS文档https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/NSURLSessionConcepts/NSURLSessionConcepts.html的注释,如果我们取消urlsession,那么它将被报告为已取消,但不会响应401错误。

Note: NSURLSession does not report server errors through the error parameter. The only errors your delegate receives through the error parameter are client-side errors, such as being unable to resolve the hostname or connect to the host. The error codes are described in URL Loading System Error Codes.
Server-side errors are reported through the HTTP status code in the NSHTTPURLResponse object. For more information, read the documentation for the NSHTTPURLResponse and NSURLResponse classes.