19

構築中の RESTful Web サービスに接続するために使用する cocoa クラスをセットアップしました。PHP バックエンドで HTTP 基本認証を使用することにしました…</p>

<?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 を使用しています。これは、Apple のドキュメントでは認証のサポートが少ないことを理解しています。

しかし、それはまったく可能ですか?NSURLProtectionSpaces または NSURLCredentials または認証クラスのいずれかを使用せずに、Cookie 認証を非常に簡単に行うことができます。また、Cocoa 認証クラスについて詳しく読むことができるリソースはありますか?

ありがとう。

更新: mikeabdullahuk あなたが提供したコード (2 番目の例) は、私が書いたものとほとんど同じです。さらに調査を行ったところ、NSURLConnection がエラーを返していることがわかりました…</p>

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

コードは NSURLErrorUserCancelledAuthentication に対応します。どうやら私のコードは NSURLCredentialStorage にアクセスしておらず、代わりに認証をキャンセルしています。これは、PHP の HTTP 認証機能と関係がありますか? この時点でかなり混乱しています。

4

4 に答える 4

63

同期NSURLConnectionは絶対に動作しNSURLCredentialStorageます。通常の動作は次のとおりです。

  1. NSURLConnectionサーバーからページをリクエストします
  2. サーバーは 401 応答で応答します
  3. NSURLConnectionURLから収集できる資格情報を確認します
  4. URL が完全な資格情報 (ユーザー名とパスワード) を提供しなかった場合は、ギャップを埋めるためにNSURLConnectionも相談しますNSURLCredentialStorage
  5. 完全な資格情報がまだ決定されていない場合は、資格情報を要求NSURLConnectionするデリゲート メソッドを送信します。-connection:didReceiveAuthenticationChallenge:
  6. が最終的に完全な資格情報を取得した場合、NSURLConnection承認データを含む元の要求を再試行します。

同期接続方式を使用すると、ステップ 5 のカスタム認証を提供する機能だけが失われます。そのため、URL に認証資格情報を事前に提供するかNSURLCredentialStorage、要求を送信する前に配置することができます。例えば

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

[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];
于 2009-02-02T00:01:26.100 に答える
12

401 またはその他の認証チャレンジが受け入れられない/不可能な状況では、ダミーの CFHTTPMessage を使用して認証行を生成し、それを 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 ではない状況や、サーバーが実際に HTTP 401 を送信していないために NSURLRequest が NSURLCredentialStorage の参照を拒否する状況 (たとえば、代わりに通常のページ)。

于 2009-02-03T23:34:17.103 に答える
0

クレデンシャルを保護スペースのデフォルトのクレデンシャルとして設定します。

// 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];

この時点で、設定したものと一致する保護スペースを使用してチャレンジされる後続の NSURLConnection は、この資格情報を使用します。

于 2013-02-13T22:38:51.337 に答える
0

mikeabdullahukの答えは良いですが、セッションごとの代わりに NSURLCredentialPersistencePermanent を使用すると、資格情報がユーザーのキーチェーンに保存されるため、次回は保護スペースのデフォルトの資格情報の nil 以外の値について NSURLCredentialStorage を確認できます。 nil 以外の値で、資格情報を渡すことができます。私は現在、このメソッドを私が書いているdelicious.comクライアントに使用していますが、テストでは非常にうまく機能します。

于 2009-02-02T17:54:18.680 に答える