構築しているRESTfulWebサービスに接続するために使用するcocoaクラスを設定しています。 PHPバックエンドで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を使用しています。これは、Appleドキュメントの状態では認証のサポートが少ないことを理解しています。
しかし、それはまったく可能ですか? NSURLProtectionSpaces、NSURLCredentials、または任意の認証クラスを使用せずに、Cookie認証を非常に簡単に行うことができます。また、Cocoa認証クラスについてもっと読むことができるリソースはありますか?
ありがとう。
更新:mikeabdullahukあなたが提供したコード(2番目の例)は、私が書いたものとほとんど同じです。さらに調査を行ったところ、NSURLConnectionがエラーを返していることがわかりました…
Error Domain=NSURLErrorDomain Code=-1012 UserInfo=0x1a5170 "Operation could not be completed. (NSURLErrorDomain error -1012.)"
コードはNSURLErrorUserCancelledAuthenticationに対応しています。したがって、私のコードはNSURLCredentialStorageにアクセスしておらず、代わりに認証をキャンセルしているようです。これはPHP HTTP認証関数と関係がありますか?この時点でかなり混乱しています。
同期NSURLConnection
はNSURLCredentialStorage
で絶対に機能します。通常の動作は次のとおりです。
NSURLConnection
はサーバーにページを要求しますNSURLConnection
は、URLから収集できる資格情報を確認しますNSURLConnection
はNSURLCredentialStorage
も参照してギャップを埋めますNSURLConnection
は資格情報を要求する-connection:didReceiveAuthenticationChallenge:
デリゲートメソッドを送信します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];
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の参照を拒否する状況には耐性があります(たとえば、代わりに通常のページ)。
Mikeabdullahukの答えは良いと思いますが、セッションごとではなくNSURLCredentialPersistencePermanentを使用すると、ユーザーのキーチェーンに資格情報が保存されるため、次回、NSURLCredentialStorageで保護スペースのデフォルトの資格情報のnil以外の値を確認できます。 nil以外の値を指定すると、資格情報を渡すことができます。現在、このメソッドを、作成中のdelicious.comクライアントに使用しており、テストで非常にうまく機能します。
資格情報を保護スペースのデフォルトの資格情報として設定します。
// 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は、この資格情報を使用します