AFNetworking 2.0 and HTTP Basic Authentication

2019-01-21 01:46发布

问题:

Can't find AFHTTPClient on AFNetworking 2.0, to use:

AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://examplewebsite.com]];

[client setAuthorizationHeaderWithUsername:@"username" password:@"password"];

How it needs to be manage on AFNetworking 2.0?

回答1:

AFNetworking 2.0 new architecture use serializers for creating requests and parsing responses. In order to set the authorization header, you should first initialize a request operation manager that replaces the AFHTTPClient, create a serializer and then call the dedicated method to set the header.

For example you code would become:

AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:@"http://examplewebsite.com"]];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"userName" password:@"password"];

You should read the documentation and the migration guide to understand the new concepts that come with the version 2.0 of AFNetworking.



回答2:

Here is an example of performing basic HTTP authentication with AFNetworking 2.0 using NSURLCredential. The advantage of this approach over using the AFHTTPRequestSerializer setAuthorizationHeaderFieldWithUsername:password: method is that you can automatically store the username and password in the keychain by changing the persistence: parameter of NSURLCredential. (See this answer.)

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

NSURLCredential *credential = [NSURLCredential credentialWithUser:@"user" password:@"passwd" persistence:NSURLCredentialPersistenceNone];

NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:@"GET" URLString:@"https://httpbin.org/basic-auth/user/passwd" parameters:nil];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCredential:credential];
[operation setResponseSerializer:[AFJSONResponseSerializer alloc]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"Success: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Failure: %@", error);
}];
[manager.operationQueue addOperation:operation];


回答3:

As @gimenete mentions multipart requests will fail when using @titaniumdecoy credential approach as this is applied in the challenge block and the current version of AFNetworking has an issue with this. Instead of using the credential approach you can embed the authentication in the NSMutableRequest header

    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"PUT"  URLString:path parameters:myParams constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
                    [formData appendPartWithFileData:imageData name:imageName fileName:imageName mimeType:@"image/jpeg"];
            } error:&error];    
    NSString *authStr = [NSString stringWithFormat:@"%@:%@", [self username], [self password]];
    NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
    NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodedString]];
    [request setValue:authValue forHTTPHeaderField:@"Authorization"];

Where you will need to use a third party BASE64 encoding library such as NSData+Base64.h and .m File from Matt Gallaghers pre ARC BASE64 solution