2015-04-01 52 views
3

我有一個Web API,如果一切正常,對於特定請求返回狀態碼200,如果用戶未根據授權令牌登錄,則返回401。如果響應狀態爲200,則一切正常,但如果響應狀態爲401,則返回連接錯誤,代碼爲-1012,響應爲零時似乎無法正常工作。NSURLConnection返回錯誤,而不是響應401

所以,下面的代碼:

[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 

如果響應狀態是200,而如果狀態代碼是401,我將獲得:

2015-04-01 16:05:55.988 MyProject[3633:695836] (null) 
2015-04-01 16:05:55.992 MyProject[3633:695836] Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x146137c0 {NSErrorFailingURLKey=*SOME_URL*, NSErrorFailingURLStringKey=*SOME_URL*, NSUnderlyingError=0x1459e6d0 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1012.)"} 
2015-04-01 16:05:55.992 MyProject[3633:695836] response status code: 0 

如果我使用Postman或Android設備執行相同的請求,我將獲得狀態碼401以及以下標題(複製f rom postman):

Connection → keep-alive 
Content-Length → 30 
Content-Type → application/json 
Date → Wed, 01 Apr 2015 13:07:34 GMT 
Server → Wildfly 8 
X-Powered-By → Undertow 1 

是否有任何修復或者可能會給我一些準確的響應狀態的庫?我搜索了一下關於-1012的錯誤,但找不到很多,我不想基於此。

編輯:經過一番研究,我在Appl的文檔中發現了以下聲明:「如果需要進行身份驗證才能下載請求,則必須將所需的憑證指定爲URL的一部分,如果身份驗證失敗或憑據丟失,連接將嘗試繼續沒有憑據。

但是我怎麼能知道這個錯誤是否會在401狀態之後?它可以出現在另一種類型的請求之後嗎?

回答

1

爲了得到401個狀態碼,我想你會需要實現協議NSURLConnectionDelegate然後connection:didReceiveAuthenticationChallenge:

所以,你還需要通過代理,也許使用[NSURLConnection connectionWithRequest:request delegate:self]

而且,如果您不嘗試實施身份驗證質詢,我寧願始終返回200狀態碼,但使用不同的json內容。

希望它可以幫助。

+0

正如我所見,連接:didReceiveAuthenticationChallenge:已被棄用爲OS.x(可能在未來的iOS也是如此),我認爲連接:willSendRequestForAuthenticationChallenge:也會幫助我,對不對? 那我在哪裏得到答案? – 2015-04-01 14:02:57

+1

將得到連接的響應:didReceiveResponse:,我猜。 – 2015-04-01 14:09:31

+0

您可以使用connection:didReceiveResponse,connection:didReceiveData和connectionDidFinishLoading。所以,你也需要實現NSURLConnectionDataDelegate協議。 – 2015-04-01 14:15:52

2

檢查401錯誤,你可以這樣做:

if (error != nil && error.code == NSURLErrorUserCancelledAuthentication) { 
    // do something for 401 error 
} 

希望這有助於

0

我有一個Web API,對於一個特定的請求返回狀態代碼200 如果一切順利好的,如果用戶沒有根據 授權令牌登錄,則爲401。如果響應狀態 爲200,但一切正常,但如果響應狀態爲 401,則返回連接錯誤,並返回代碼-1012,而響應 爲零則似乎無法正常工作。

我已經完全運行到相同的問題,REST API調用在Android和Postman中返回401,但iOS中的狀態碼0與代碼-1012發生連接錯誤。

您可以在this SO貼子中找到關於此問題的更多信息。

似乎是發生異步和同步請求的iOS錯誤(或至少非常奇怪的方法)。

我發佈這只是爲了防止這可能會有助於其他人碰到相同的問題。我在代碼中管理401狀態的方法是,在請求之後調用一個方法來檢查每個託管http狀態碼。

該方法接收(NSError **)錯誤[(NSHTTPURLResponse *)響應的StatusCode]

這是401部分 - 使用用戶信息結構中存儲的錯誤詳細信息。

// 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 
    ... 
} 

另一種方法是直接檢查上述@ThuanDINH建議的錯誤代碼(-1012)。 (編輯目標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碼開關)。

Here你可以找到所有NSURLError代碼列表的SO問題。

0

基於蘋果文檔https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/NSURLSessionConcepts/NSURLSessionConcepts.html

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. 

我們需要確保我們不會在我們的代碼取消會話。例如,當beforeFailureCount> 1時,我在didReceiveChallenge委託方法中調用NSURLSessionAuthChallengeCancelAuthenticationChallenge。這是抑制401響應並調用didReceiveResponse。

當我將以上值更改爲NSURLSessionAuthChallengePerformDefaultHandling時,我在didReceiveResponse委託方法中收到401 Unauthorized響應並按預期工作。

相關問題