nsurlConnectionはデフォルトの資格情報を使用しません
-
28-10-2019 - |
質問
私は接続しようとしています http://cmis.demo.nuxeo.org/nuxeo/atom/cmis/ と NSURLConnection
. 。このデモWebサービスはです 文書化 認証を要求する(ログイン:管理者 /パスワード:管理者)。
編集: :このWebサービスは現在、認証チャレンジを送信しましたが、質問が尋ねられた時点ではありませんでした。
このWebサービス ではない 認証チャレンジを送信するので、使用できません connection:didReceiveAuthenticationChallenge:
委任方法。代わりに、デフォルトを設定します NSURLCredential
共有資格情報ストレージ。残念ながら、このデフォルトの資格情報は使用されません NSURLConnection
.
これが私のコードです(iOS 5でテストされたARCを使用):
@implementation ViewController
{
NSMutableData *responseData;
}
- (IBAction) connect:(id)sender
{
NSString *user = @"Administrator";
NSString *password = @"Administrator";
NSURL *nuxeoURL = [NSURL URLWithString:@"http://cmis.demo.nuxeo.org/nuxeo/atom/cmis/"];
NSURLCredential *credential = [NSURLCredential credentialWithUser:user password:password persistence:NSURLCredentialPersistenceForSession];
NSString *host = [nuxeoURL host];
NSNumber *port = [nuxeoURL port];
NSString *protocol = [nuxeoURL scheme];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:host port:[port integerValue] protocol:protocol realm:nil authenticationMethod:NSURLAuthenticationMethodHTTPBasic];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nuxeoURL];
BOOL manuallyAddAuthorizationHeader = NO;
if (manuallyAddAuthorizationHeader)
{
NSData *authoritazion = [[NSString stringWithFormat:@"%@:%@", user, password] dataUsingEncoding:NSUTF8StringEncoding];
NSString *basic = [NSString stringWithFormat:@"Basic %@", [authoritazion performSelector:@selector(base64Encoding)]];
[request setValue:basic forHTTPHeaderField:@"Authorization"];
}
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
responseData = [NSMutableData data];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"connectionDidFinishLoading:%@", connection);
NSLog(@"%@", [[NSString alloc] initWithData:responseData encoding:NSISOLatin1StringEncoding]);
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"connection:%@ didFailWithError:%@", connection, error);
}
@end
デフォルトの資格情報は使用されていないため、XMLの代わりにHTML(ログインページ)を受信します。設定した場合 manuallyAddAuthorizationHeader
変数 YES
, 、その後、承認が機能し、XMLを受け取ります。
私の質問は、なぜそうするのですか NSURLConnection
ではない 自動的 デフォルトを使用します NSURLCredential
?
解決
認証チャレンジなしでデフォルトの資格情報を送信することは、特にプレーンHTTPを介して通信している場合には、安全ではないと見なされます。 http仕様はあなたが言っています できる 資格情報を積極的に送信しますが、通常、認証チャレンジを待つ必要があります。そして、それはココアがデフォルトで提供する動作です。
資格情報を積極的に送信する必要がある場合は、ヘッダーを手動で追加する必要があります。あなたはそれを自分でベース64エンコードすることができます、またはあなたは CFHTTP
そうするように、あなたのためにそれをする機能:
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);
次に、を設定します authorizationString
として Authorization
あなたのヘッダー NSURLRequest
.
(コードは露骨にコピーされました https://stackoverflow.com/a/509480/100478, 、私は何度も同様のコードを書いていますが)
他のヒント
HTTPは多くの異なる認証方法(Basic、Digest、Kerberosなど)をサポートしているため、 NSURLConnection
サーバーから認証チャレンジを受信する前に資格情報を送信することはできません。これは、それらを送信する方法がわからないためです。
BJの回答はクライアント側の問題を解決する可能性がありますが、実際の問題はサーバーです。内部的には、nsurlconnectionはそれを代表的な方法と同等に使用します connection:didReceiveAuthenticationChallenge:
および他の認証方法。これは、それが適用できる資格情報を探している場所です NSURLCredentialStorage
。あなたの場合、これは起こっていないようです。これらのメソッドを呼び出すためには、サーバーは40x HTTPステータスコードを提供する必要があるだけでなく、www-authenticateヘッダーを含める必要があります。これにより、NSURLCONNECTIONが認証チャレンジに回答しようとするように指示されます。サーバーがこれを含めていない可能性があり、それがクライアントが資格情報を送信していない理由です。