【问题标题】:AFOAuth2Client and refresh tokenAFOAuth2Client 和刷新令牌
【发布时间】:2013-02-26 21:06:46
【问题描述】:

如何在 iPad 应用中实现 Oauth?

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

是否有任何方法可以在类中实现它,还是我们必须以自己的方式实现它?如何查看token是否过期?

【问题讨论】:

    标签: ios ipad oauth-2.0 afnetworking


    【解决方案1】:

    我解决这个问题的方法是用一个代码块包装我的所有请求,如果需要,它将刷新访问令牌,例如

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

    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

    【讨论】:

    • 此外,您可以将凭证的存储移动到属性的设置器。
    • 这似乎取决于令牌上的 expires_in ,它假设您的时钟与服务器相当密切地同步,即使在网络滞后(这可能是也可能不是问题)并且您的服务器确实正确设置了 expires_in 值。建议使用 expires_in,但规范中不需要。这表明在不支持 expires_in 的服务器上,应该在收到带有令牌的请求的错误后进行刷新。触发刷新的典型错误是 401。只是想指出,虽然此解决方案可能有效,但它可能并不总是有效。
    • @ptoinson 您是对的,我遇到了这个问题,您是否有任何代码示例可以共享执行刷新然后使用刷新的令牌发送请求?我正在尝试观察 AFNetworkingOperationDidFinishNotification 但无法提出令人满意的解决方案。
    • @Newcode:我创建了一个 AFHTTPClient 子类,它使用委托模式和扩展的失败块来获取新令牌:github.com/booiiing/AFAuthorizedClient 只需根据您的需要调整现有的委托或实现您自己的委托.请注意,还有其他(可能更容易)的可能性来确保正确的凭据,包括使用对安全资源的(小的、固定的)请求的操作依赖性或挂钩到现有的 AFNetworking 身份验证机制。根据您的服务器,这些可能会或可能不会更可取。
    • @Newcode:我已经创建了代码来解决这个问题。但是,我在 NSNetworking 之上有几个层,包括 RestKit。我几乎只是寻找 401 响应,缓存生成 401 的请求,刷新令牌并重试触发 401 的请求。它变得非常复杂,因为我也可以并行处理请求并且可以在任何情况下获得 401其中之一。当令牌已经在进行中时,真的不想进行令牌刷新。 patric.schenke 的代码将帮助您完成大部分工作。
    猜你喜欢
    • 1970-01-01
    • 2017-11-20
    • 2018-02-27
    • 2015-08-22
    • 1970-01-01
    • 2018-09-29
    • 2021-08-20
    • 2020-06-12
    • 1970-01-01
    相关资源
    最近更新 更多