NSURLConnection does not use default credentials

I am trying to connect to http://cmis.demo.nuxeo.org/nuxeo/atom/cmis/ using NSURLConnection . This demo web service is documented to request authentication (username: Administrator / Password: Administrator).

Change This web service now sends an authentication request, but no question has been asked.

This web service does not send an authentication request, so I cannot use the connection:didReceiveAuthenticationChallenge: delegate method. Instead, I set the default NSURLCredential to the shared credential store. Unfortunately, this NSURLConnection is not used by NSURLConnection by default.

Here is my code (using ARC tested on iOS 5):

 @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 

Since no credentials are used by default, I get html (login page) instead of xml. If I set the manuallyAddAuthorizationHeader variable to YES , then authorization works, and I get xml.

My question is: why NSURLConnection n't NSURLConnection automatically use NSURLCredential by default?

+4
source share
3 answers

Sending default credentials without authentication is considered unsafe, especially when you are exchanging simple HTTP. The HTTP specification says that you can send credentials proactively, but usually you should wait for authentication. And this is the behavior that Cocoa provides by default.

If you need to proactively send credentials, you will have to manually add the headers yourself. You can simply encode it base-64 yourself, or you can use the CFHTTP functions to do this for you, for example:

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

Then just set authorizationString as the Authorization header in NSURLRequest .

(The code is clearly copied from fooobar.com/questions/266170 / ... , although I myself wrote this code on my own.)

+8
source

Because HTTP supports many different authentication methods (Basic, Digest, Kerberos, etc.), NSURLConnection cannot send credentials before it receives an authentication request from the server because it does not know how to send them.

+3
source

While the BJ answer may solve your client-side problem, the real problem is the server. Internally, NSURLConnection will use its own equivalent delegate method connection:didReceiveAuthenticationChallenge: and other authentication methods. Here he searches for credentials that he can apply from NSURLCredentialStorage . In your case, this does not seem to be happening. For these methods that need to be called, the server must provide not only a 40x HTTP status code, but also must include the WWW-Authenticate header. This tells NSURLConnection to try to answer the authentication call. Your server probably does not enable this, and why the client is not sending credentials.

0
source

Source: https://habr.com/ru/post/1397619/


All Articles