2013-02-01 108 views
10

如何在iPad应用程序中实现Oauth?AFOAuth2Client和刷新令牌

AFOAuth2Client如何管理oauth 2.0中的刷新令牌机制?

有没有实现它的类中的任何方法还是我们必须实现它以自己的方式?如何检查令牌是否过期?

回答

11

,我已经解决了,这是给我换一个代码块中的所有请求,如果需要,例如它会刷新访问令牌的方式

添加一些类型定义为成功和失败的块:

typedef void (^YFRailsSaasApiClientSuccess)(AFJSONRequestOperation *operation, id responseObject); 
typedef void (^YFRailsSaasApiClientFailure)(AFJSONRequestOperation *operation, NSError *error); 

然后该请求的方法是:

- (void)getProductsWithSuccess:(YFRailsSaasApiClientSuccess)success failure:(YFRailsSaasApiClientFailure)failure { 
    NSLog(@"getProductsWithSuccess"); 

    success = ^(AFJSONRequestOperation *operation, id responseObject) { 
     [self getPath:@"api/1/products" 
      parameters:nil 
       success:^(AFHTTPRequestOperation *operation, id responseObject) { 
        NSLog(@"getProductsWithSuccess: success"); 

        // TODO: handle response 

        if (success) { 
         success((AFJSONRequestOperation *)operation, responseObject); 
        } 
       } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
        NSLog(@"getProductsWithSuccess: failure"); 
       if (failure) { 
        failure((AFJSONRequestOperation *)operation, error); 
       } 
      }]; 
    }; 

    [self refreshAccessTokenWithSuccess:success failure:failure]; 
} 

并且检查令牌到期,如果需要刷新它的方法是:

- (void)refreshAccessTokenWithSuccess:(YFRailsSaasApiClientSuccess)success failure:(YFRailsSaasApiClientFailure)failure { 
    NSLog(@"refreshAccessTokenWithSuccess"); 

    if (self.credential == nil) { 
     if (failure) { 
      NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary]; 
      [errorDetail setValue:@"Failed to get credentials" forKey:NSLocalizedDescriptionKey]; 
      NSError *error = [NSError errorWithDomain:@"world" code:200 userInfo:errorDetail]; 
      failure(nil, error); 
     } 
     return; 
    } 

    if (!self.credential.isExpired) { 
     NSLog(@"refreshAccessTokenWithSuccess: credential has not expired"); 

     if (success) { 
      success(nil, nil); 
     } 
     return; 
    } 

    NSLog(@"refreshAccessTokenWithSuccess: refreshing credential"); 

    [self authenticateUsingOAuthWithPath:@"oauth/token" 
          refreshToken:self.credential.refreshToken 
           success:^(AFOAuthCredential *newCredential) { 
            NSLog(@"Successfully refreshed OAuth credentials %@", newCredential.accessToken); 
            self.credential = newCredential; 
            [AFOAuthCredential storeCredential:newCredential 
                withIdentifier:self.serviceProviderIdentifier]; 

            if (success) { 
             success(nil, nil); 
            } 
           } 
           failure:^(NSError *error) { 
            NSLog(@"An error occurred refreshing credential: %@", error); 
            if (failure) { 
             failure(nil, error); 
            } 
           }]; 
} 

完整的源代码了在GitHub上:https://github.com/yellowfeather/rails-saas-ios

+0

此外,您可以将凭证的存储移动到财产的设置者。 – conradev

+2

看来,这取决于令牌上的expires_in,它假定您的时钟与服务器同步的时间非常接近,即使在网络滞后(这可能会也可能不是问题)并且您的服务器确实设置了expires_in值正常。建议使用expires_in,但在规范中不需要。这表明在不支持expires_in的服务器上,刷新应在收到带有令牌的请求的错误后完成。典型的触发刷新的错误是401.只是想指出,虽然这个解决方案可能工作,但它可能并不总是工作。 – ptoinson

+0

@ptoinson你是对的,我遇到了这个问题,你有任何代码示例共享执行刷新,然后发送请求与刷新的令牌?我正在尝试观察AFNetworkingOperationDidFinishNotification,但无法提出令人满意的解决方案。 – Newcode