2012-02-21 18 views
4

http://cmis.demo.nuxeo.org/nuxeo/atom/cmis/に接続しようとしています。NSURLConnectionです。このデモウェブサービスは、認証が必要なdocumentedです(ログイン:管理者/パスワード:管理者)。NSURLConnectionはデフォルトの資格情報を使用しません

を編集します。この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を使用していますか?

答えて

8

認証の挑戦なしにデフォルトの認証情報を送信することは安全ではないと考えられます。特に、通常のHTTP経由で通信している場合は安全です。 HTTP仕様によれば、が事前に資格情報を送信できますが、通常は認証の挑戦を待つべきです。これがデフォルトでCocoaが提供する動作です。

資格情報を積極的に送信する必要がある場合は、手動でヘッダーを手動で追加する必要があります。

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); 

それからちょうどあなたのNSURLRequestAuthorizationヘッダーとしてauthorizationStringを設定します。あなただけのベース64エンコード、それは自分自身、またはあなたがそうのように、あなたのためにそれを行うにはCFHTTP機能を使用することができますをすることができます。

(私は自分自身何度も同様のコードを書いているのにコードが、https://stackoverflow.com/a/509480/100478から露骨にコピーされた。)

3

HTTPは、多くの異なる認証方法(など基本、ダイジェスト、Kerberosを、)サポートとして、NSURLConnection前に資格情報を送信することはできません。サーバーから認証チャレンジを受信するため、送信する方法がわからないためです。

+0

'NSURLProtectionSpace'を' authenticationMethod:NSURLAuthenticationMethodHTTPBasic'で明示的に作成しましたので、どのような方法を使うのかと考えました。 – 0xced

0

BJの答えはクライアント側で問題を解決するかもしれませんが、実際の問題はサーバーです。 内部的にNSURLConnectionは、それ自体のデリゲートメソッドconnection:didReceiveAuthenticationChallenge:およびそれ以外の認証メソッドと同等のものを使用します。これは、NSURLCredentialStorageから適用できる認証情報を検索する場所です。あなたの場合、これは起こっていないようです。これらのメソッドを呼び出すには、サーバは40x HTTPステータスコードを与えるだけでなく、WWW-Authenticateヘッダを含める必要があります。これは、NSURLConnectionに認証チャレンジへの応答を試みるように指示します。サーバーにはこれが含まれていない可能性があります。そのため、クライアントは資格情報を送信しません。

関連する問題