Objective c NSURLConnection返回错误,而不是401的响应

Objective c NSURLConnection返回错误,而不是401的响应,objective-c,nsurlconnection,nsurlrequest,Objective C,Nsurlconnection,Nsurlrequest,我有一个web API,对于特定请求,如果一切正常,则返回状态代码200,如果用户未基于授权令牌登录,则返回401。如果响应状态为200,则一切正常,但如果响应状态为401,则似乎无法正常工作,返回代码为-1012的连接错误,而响应为nil 因此,以下代码: [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data,

我有一个web API,对于特定请求,如果一切正常,则返回状态代码200,如果用户未基于授权令牌登录,则返回401。如果响应状态为200,则一切正常,但如果响应状态为401,则似乎无法正常工作,返回代码为-1012的连接错误,而响应为nil

因此,以下代码:

[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    NSLog(@"%@", response);
    NSLog(@"%@", connectionError);

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
    int statusCode = (int)[httpResponse statusCode];
    NSLog(@"response status code: %d", statusCode);
将显示

2015-04-01 15:58:18.511 MyProject[3618:694604] <NSHTTPURLResponse: 0x155facc0> { URL: *SOME_URL* } { status code: 200, headers {
    "Access-Control-Allow-Headers" = "Content-Type, Accept, X-Requested-With";
    "Access-Control-Allow-Methods" = "POST, GET, PUT, UPDATE, OPTIONS";
    "Access-Control-Allow-Origin" = "*";
    Connection = "keep-alive";
    "Content-Type" = "application/json";
    Date = "Wed, 01 Apr 2015 12:58:14 GMT";
    Server = "Wildfly 8";
    "Transfer-Encoding" = Identity;
    "X-Powered-By" = "Undertow 1";
} }
2015-04-01 15:58:18.513 MyProject[3618:694604] (null)
2015-04-01 15:58:18.513 MyProject[3618:694604] response status code: 200
如果我使用Postman或Android设备执行相同的请求,我将获得带有以下标题的状态代码401(复制自Postman):

是否有任何修复或库可以给我一些准确的响应状态?我搜索了一些关于-1012错误的信息,但是没有找到太多,我也不想基于此

编辑:经过一点研究,我在Appl的文档中发现了以下语句:如果下载请求需要身份验证,则必须将所需的凭据指定为URL的一部分。如果身份验证失败或凭据丢失,则连接将尝试在没有凭据的情况下继续。


但是我怎么知道这个错误是否会在401状态之后发生呢?它能在另一种请求之后出现吗?

为了获得401状态码,我认为您需要实现协议
NSURLConnectionLegate
,然后
连接:didReceiveAuthenticationChallenge:

因此,您还需要传递委托,可能需要使用
[NSURLConnection connectionWithRequest:request delegate:self]

而且,如果您不想实现身份验证挑战,我宁愿总是返回200状态码,但包含不同的json内容


希望能有所帮助。

要检查401错误,可以执行以下操作:

if (error != nil && error.code == NSURLErrorUserCancelledAuthentication) {
    // do something for 401 error
}
希望这有帮助

我有一个web API,对于特定的请求,它返回状态代码200 如果一切正常,401如果用户未基于 授权令牌。如果响应状态为 是200,但如果响应状态为,则似乎无法正常工作 401,返回代码为-1012的连接错误,而响应 是零

我遇到了完全相同的问题,RESTAPI调用在Android和Postman中返回401,但在iOS中返回状态代码0,连接错误代码为-1012

您可以在SO post中找到有关此问题的更多信息

似乎是一个iOS错误(或者至少是非常奇怪的方法)同时发生在异步和同步请求中

我发布这篇文章只是为了防止其他人遇到同样的问题。我在管理401状态的代码中所做的就是在请求之后调用一个方法来检查每个托管http状态代码

该方法接收(NSError**)错误[(NSHTTPURLResponse*)响应状态码]

这是401部分-使用存储在userInfo结构中的错误详细信息

// Auth failed or token problems
if (statusCode == 0 && [error userInfo] != nil) {

    // Get error detailed informations
    NSDictionary *userInfo = [error userInfo];
    NSString *errorString = [[userInfo objectForKey:NSUnderlyingErrorKey] localizedDescription];

    // If error message is of type authFailed or returns iOS code -1012 meaning auth failed
    if ([errorString containsString:@"kCFErrorDomainCFNetwork"] || [errorString containsString:@"-1012"]) {
        NSLog(@"%@ - ConnectionError - Code 401 - Cause: authentication failed, token is invalid or expired", type);
    } else {
        NSLog(@"%@ - ConnectionError - Cause: generic auth error", type);
    }

    // Alert user that auth failed
    ...
}
另一种方法是直接检查这个错误代码(-1012),正如上面@ThuanDINH所建议的那样。(编辑了目标c的答案)

我的代码可以更改为:

// Auth failed - token problems
if (statusCode == 0 && [error code] == NSURLErrorUserCancelledAuthentication) {

    // If error code is UserCanceledAuthentication
    MPLog(MPLogLevelInfo, @"%@ - ConnectionError - Cause: authentication failed, token is invalid or expired", type);

    // Alert user that auth failed
    ...
}
但通过这种方式,您将无法处理所有其他错误(您需要打开每个NSURLError代码)


您可以在所有NSURLError代码的列表中找到SO问题。

基于Apple文档

我们需要确保代码中没有取消会话。例如,当以前的FailureCount>1时,我在didReceiveChallenge委托方法中调用了
NSURLSessionAuthChallengeCancelAuthenticationChallenge
。这是对401的回应,也是对didReceiveResponse的呼吁


当我将上述值更改为
NSURLSessionAuthenticationChallengePerformDefaultHandling
时,我在didReceiveResponse委托方法中收到了401个未经授权的响应,并按预期工作。

如我所见,connection:didReceiveAuthenticationChallenge:在os.x中已被弃用(可能在将来的ios中也会如此),我认为连接:willSendRequestForAuthenticationChallenge:也会帮助我,对吗?那么从哪里获得响应呢?我猜将获得连接为:didReceiveResponse:的响应。您可以使用连接:didReceiveResponse、连接:didReceiveData和ConnectiondFinishLoading。因此,您还需要实现NSURLConnectionDataDelegate协议。您是否碰巧知道代码为-1012的connectionError是否专门用于此操作?你能用其他方法得到错误吗?现在将错误作为401响应处理会容易得多,因为我有很多不同的请求。不幸的是,现在还不能选择将服务器的所有响应都标记为200。不幸的是,我认为这是出于设计:(.我想我已经在c#上看到过同样的行为,在c#上,您需要抛出异常,然后获得响应。
// Auth failed or token problems
if (statusCode == 0 && [error userInfo] != nil) {

    // Get error detailed informations
    NSDictionary *userInfo = [error userInfo];
    NSString *errorString = [[userInfo objectForKey:NSUnderlyingErrorKey] localizedDescription];

    // If error message is of type authFailed or returns iOS code -1012 meaning auth failed
    if ([errorString containsString:@"kCFErrorDomainCFNetwork"] || [errorString containsString:@"-1012"]) {
        NSLog(@"%@ - ConnectionError - Code 401 - Cause: authentication failed, token is invalid or expired", type);
    } else {
        NSLog(@"%@ - ConnectionError - Cause: generic auth error", type);
    }

    // Alert user that auth failed
    ...
}
// Auth failed - token problems
if (statusCode == 0 && [error code] == NSURLErrorUserCancelledAuthentication) {

    // If error code is UserCanceledAuthentication
    MPLog(MPLogLevelInfo, @"%@ - ConnectionError - Cause: authentication failed, token is invalid or expired", type);

    // Alert user that auth failed
    ...
}
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.