2009-02-01 49 views
19

我有一個可用類,我想用它來連接到我正在構建的RESTful Web服務。我決定使用HTTP基本身份驗證我的PHP後臺是這樣的...我可以使用NSURLCredentialStorage進行HTTP基本認證嗎?

<?php 
if (!isset($_SERVER['PHP_AUTH_USER'])) { 
    header('WWW-Authenticate: Basic realm="My Realm"'); 
    header('HTTP/1.0 401 Unauthorized'); 
    //Stuff that users will see if they click 'Cancel' 
    exit; 
} 
else { 
    //Validation Code 
    echo "You entered info."; 
} 
?> 

在這一點上,我使用同步NSURLConnection的,這是我理解的蘋果文檔狀態有認證的支持較少。

但是它甚至有可能嗎?我可以很容易地進行cookie身份驗證,無需NSURLProtectionSpaces或NSURLCredentials或任何身份驗證類。另外,是否有任何資源可以閱讀關於Cocoa認證類的更多信息?

謝謝。

更新:mikeabdullahuk 您提供的代碼(第二個示例)與我所寫的代碼幾乎相同。我做得更多一些調查,並發現NSURLConnection的返回錯誤......

Error Domain=NSURLErrorDomain Code=-1012 UserInfo=0x1a5170 "Operation could not be completed. (NSURLErrorDomain error -1012.)" 

的代碼對應於NSURLErrorUserCancelledAuthentication。所以顯然我的代碼沒有訪問NSURLCredentialStorage,而是取消了身份驗證。這可能與PHP HTTP身份驗證功能有關嗎?在這一點上我很困惑。

回答

62

同步NSURLConnection絕對可以與NSURLCredentialStorage一起使用。這裏是如何的東西平時的工作:從服務器

  1. NSURLConnection請求的頁面
  2. 服務器用401響應
  3. NSURLConnection看,看看有什麼憑據可以從URL
  4. 如果URL中收集回覆沒提供完整的憑據(用戶名和密碼),NSURLConnection亦會諮詢NSURLCredentialStorage的空白填補
  5. 如果完整憑據有仍然未被確定,NSURLConnection將發送-connection:didReceiveAuthenticationChallenge:委託方法要求憑據
  6. 如果NSURLConnection現在最終具有完整憑證,它會重試原始請求,包括授權數據。

通過使用同步連接方法,您只需要在步驟5上失去了提供自定義驗證的能力。因此,您可以預先在URL中提供身份驗證憑據,也可以在發送請求之前將其置於NSURLCredentialStorage之內。例如

NSURLRequest *request = 
    [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://user:[email protected]"]]; 

[NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL]; 

或:

NSURLCredential *credential = [NSURLCredential credentialWithUser:@"user" 
                 password:@"pass" 
                 persistence:NSURLCredentialPersistenceForSession]; 

NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] 
    initWithHost:@"example.com" 
    port:0 
    protocol:@"http" 
    realm:nil 
    authenticationMethod:nil]; 


[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential 
                forProtectionSpace:protectionSpace]; 
[protectionSpace release]; 

NSURLRequest *request = 
    [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com"]]; 

[NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL]; 
+1

我挑戰任何後續NSURLConnection的遇到了這個。我非常喜歡ObjectiveC,但我想知道是否有任何對象(特別是憑證和保護空間)必須被釋放。順便說一句,我在異步調用(initWithRequest)上實現了這個方法,仍然得到了didReceiveAuthenticationChallenge回調。 – Bill 2009-02-03 22:17:37

+0

@Bill,如果在生產代碼中使用保護空間,則需要釋放,正如我使用的+ alloc。 – 2009-02-10 12:24:25

0

我想指出mikeabdullahuk的答案是好的,但如果你還每個會話使用,而不是NSURLCredentialPersistencePermanent它會保存憑證的用戶鑰匙扣那麼下一次你可以檢查NSURLCredentialStorage爲保護空間默認憑證的非零值,如果您得到非零值,您可以將憑證傳入。我現在正在使用此方法來獲得美味。我寫的com客戶端,它在我的測試中工作得很好。

12

在這樣一種情況:401或其他認證挑戰是不可接受的/不可能,我有時使用一個虛設CFHTTPMessage以產生authetication線,然後複製回的NSURLRequest:

// assume NSString *username and *password exist and NSURLRequest *urlRequest 
// exists and is fully configured except for HTTP Basic Authentication.. 

CFHTTPMessageRef dummyRequest = 
    CFHTTPMessageCreateRequest(
     kCFAllocatorDefault, 
     CFSTR("GET"), 
     (CFURLRef)[urlRequest URL], 
     kCFHTTPVersion1_1); 
CFHTTPMessageAddAuthentication(
    dummyRequest, 
    nil, 
    (CFStringRef)username, 
    (CFStringRef)password, 
    kCFHTTPAuthenticationSchemeBasic, 
    FALSE); 
authorizationString = 
    (NSString *)CFHTTPMessageCopyHeaderFieldValue(
     dummyRequest, 
     CFSTR("Authorization")); 
CFRelease(dummyRequest); 

[urlRequest setValue:authorizationString forHTTPHeaderField:@"Authorization"]; 

這可以完全似乎一個奇怪的方式來做到這一點,但它是寬容的情況下,用戶名/密碼不是URL乾淨,並且NSURLRequest拒絕諮詢NSURLCredentialStorage,因爲服務器實際上並沒有發送HTTP 401(例如,它發送一個常規頁面)。

0

設置你的證書作爲protectionspace缺省憑證:

// Permananent, session, whatever. 
NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence: NSURLCredentialPersistencePermanent]; 
// Make sure that if the server you are accessing presents a realm, you set it here. 
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:@"blah.com" port:0 protocol:@"http" realm:nil authenticationMethod:NSURLAuthenticationMethodHTTPBasic]; 
// Store it 
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace]; 

在這一點上,那就是使用保護空間匹配你設置將只使用此憑證

相關問題