2013-01-05 31 views
5

Sử dụng AFOAuth2Client và AFNetworking trên iOS 6 Tôi có thể nhận mã thông báo truy cập nhưng không thể truy cập tài nguyên, máy chủ phản hồi với mã trạng thái 401 trái phép. Điều này là chống lại một chương trình phụ trợ API Rails 3 tùy chỉnh bằng cách sử dụng trình quản lý cửa sổ làm nhà cung cấp OAuth. sau khi mã khách hàng ruby, sử dụng đá quý OAuth2, hoạt động OK:AFOAuth2Không thể truy cập tài nguyên

client = OAuth2::Client.new(app_id, secret, site: "http://subdomain.example.com/") 
access_token = client.password.get_token('username', 'password') 
access_token.get('/api/1/products').parsed 

mã iOS là như dưới đây, trong xử lý nút đăng nhập tôi xác thực bằng cách sử dụng tên đăng nhập và mật khẩu, và lưu trữ các thông tin quan trọng:

- (IBAction)login:(id)sender { 
    NSString *username = [usernameField text]; 
    NSString *password = [passwordField text]; 

    NSURL *url = [NSURL URLWithString:kClientBaseURL]; 
    AFOAuth2Client *client = [AFOAuth2Client clientWithBaseURL:url clientID:kClientID secret:kClientSecret]; 

    [client authenticateUsingOAuthWithPath:@"oauth/token" 
           username:username 
           password:password 
           scope:nil 
           success:^(AFOAuthCredential *credential) { 
            NSLog(@"Successfully received OAuth credentials %@", credential.accessToken); 
            [AFOAuthCredential storeCredential:credential 
                 withIdentifier:client.serviceProviderIdentifier]; 
            [self performSegueWithIdentifier:@"LoginSegue" sender:sender]; 
           } 
           failure:^(NSError *error) { 
            NSLog(@"Error: %@", error); 
            [passwordField setText:@""]; 
           }]; 
} 

và tôi đã subclassed AFHTTPClient cho thiết bị đầu cuối của tôi và trong initWithBaseURL nó lấy các chứng chỉ và đặt tiêu đề cho phép với access token:

- (id)initWithBaseURL:(NSURL *)url { 
    self = [super initWithBaseURL:url]; 
    if (!self) { 
     return nil; 
    } 

    [self registerHTTPOperationClass:[AFJSONRequestOperation class]]; 
    [self setDefaultHeader:@"Accept" value:@"application/json"]; 

    AFOAuthCredential *credential = [AFOAuthCredential retrieveCredentialWithIdentifier:@"subdomain.example.com"]; 
    [self setAuthorizationHeaderWithToken:credential.accessToken]; 

    return self; 
} 

Đây có phải là cách chính xác để sử dụng AFOAuth2Client và AFNetworking không? Và bất kỳ ý tưởng tại sao điều này không hoạt động?

Trả lời

5

Managed để làm việc này bằng cách thay đổi:

AFOAuthCredential *credential = [AFOAuthCredential retrieveCredentialWithIdentifier:@"subdomain.example.com"]; 
    [self setAuthorizationHeaderWithToken:credential.accessToken]; 

tới:

AFOAuthCredential *credential = [AFOAuthCredential retrieveCredentialWithIdentifier:@"subdomain.example.com"]; 
    NSString *authValue = [NSString stringWithFormat:@"Bearer %@", credential.accessToken]; 
    [self setDefaultHeader:@"Authorization" value:authValue]; 

CẬP NHẬT

Những gì tôi đã thất bại trong việc nhận ra là AFOAuth2Client thân nó là một lớp con của AFHTTPClient như vậy có thể được sử dụng làm lớp cơ sở của lớp API, ví dụ:

@interface YFExampleAPIClient : AFOAuth2Client 

    + (YFExampleAPIClient *)sharedClient; 

    /** 

    */ 
    - (void)authenticateWithUsernameAndPassword:(NSString *)username 
             password:(NSString *)password 
             success:(void (^)(AFOAuthCredential *credential))success 
             failure:(void (^)(NSError *error))failure; 

    @end 

Và việc thực hiện trở thành:

@implementation YFExampleAPIClient 

+ (YFExampleAPIClient *)sharedClient { 
    static YFExampleAPIClient *_sharedClient = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     NSURL *url = [NSURL URLWithString:kClientBaseURL]; 
     _sharedClient = [YFExampleAPIClient clientWithBaseURL:url clientID:kClientID secret:kClientSecret]; 
    }); 

    return _sharedClient; 
} 

- (void)authenticateWithUsernameAndPassword:(NSString *)username 
            password:(NSString *)password 
            success:(void (^)(AFOAuthCredential *credential))success 
            failure:(void (^)(NSError *error))failure { 
    [self authenticateUsingOAuthWithPath:@"oauth/token" 
            username:username 
            password:password 
            scope:nil 
            success:^(AFOAuthCredential *credential) { 
             NSLog(@"Successfully received OAuth credentials %@", credential.accessToken); 
             [self setAuthorizationHeaderWithCredential:credential]; 
             success(credential); 
            } 
            failure:^(NSError *error) { 
             NSLog(@"Error: %@", error); 
             failure(error); 
            }]; 
} 

- (id)initWithBaseURL:(NSURL *)url 
      clientID:(NSString *)clientID 
       secret:(NSString *)secret { 
    self = [super initWithBaseURL:url clientID:clientID secret:secret]; 
    if (!self) { 
     return nil; 
    } 

    [self setDefaultHeader:@"Accept" value:@"application/json"]; 

    return self; 
} 

@end 

Lưu ý rằng initWithBaseURL được ghi đè để thiết lập HTTP chấp nhận tiêu đề.

mã nguồn đầy đủ có sẵn trên GitHub - https://github.com/yellowfeather/rails-saas-ios

+1

Hãy nhìn vào các tập tin https://github.com/AFNetworking/AFOAuth2Client/blob/master/AFOAuth2Client/AFOAuth2Client.h. Có một lưu ý ở trên cùng rằng bạn không nên sử dụng nó làm lớp cơ sở của bạn. – davidbitton

Các vấn đề liên quan