Ios AFOAuth2Client和刷新令牌
如何在iPad应用程序中实现Oauth 在oauth 2.0中,AFOAuth2Client如何管理刷新令牌机制Ios AFOAuth2Client和刷新令牌,ios,ipad,oauth-2.0,afnetworking,Ios,Ipad,Oauth 2.0,Afnetworking,如何在iPad应用程序中实现Oauth 在oauth 2.0中,AFOAuth2Client如何管理刷新令牌机制 是否有任何方法在类内部实现它,或者我们必须以自己的方式实现它?如何检查令牌是否过期?我解决这一问题的方法是用代码块包装我的所有请求,该代码块将在需要时刷新访问令牌,例如 为成功和失败块添加一些typedef: typedef void (^YFRailsSaasApiClientSuccess)(AFJSONRequestOperation *operation, id respon
是否有任何方法在类内部实现它,或者我们必须以自己的方式实现它?如何检查令牌是否过期?我解决这一问题的方法是用代码块包装我的所有请求,该代码块将在需要时刷新访问令牌,例如 为成功和失败块添加一些typedef:
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上提供了完整的源代码:。此外,您可以将凭证的存储移动到属性的setter。这似乎取决于令牌上的expires\u,该令牌假定您的时钟与服务器非常同步,即使在网络延迟之后(这可能是问题,也可能不是问题)而且您的服务器确实正确地设置了expires_in值。建议使用expires_in,但规范中不要求使用expires_in。这表示在不支持expires_in的服务器上,应在收到带有令牌的请求的错误后进行刷新。触发刷新的典型错误是401。我只是想指出,虽然这个解决方案可能有效,但可能并不总是有效。@ptoinson您是对的,我遇到了这个问题,您是否有任何代码示例可以共享,以执行刷新,然后使用刷新的令牌发送请求?我试图观察AFNetworkingOperationDidFinishNotification,但无法找到令人满意的解决方案。@新代码:我创建了一个AFHTTPClient子类,该子类使用委托模式和扩展故障块来获取新令牌:只需根据您的需要调整现有委托或实现您自己的委托即可。请注意,还有其他(可能更容易)的可能性来确保正确的凭据,包括使用操作依赖项和对安全资源的(小的、固定的)请求,或者挂接到AFNetworking的现有身份验证机制。取决于您的服务器,这些可能更可取,也可能不可取。@Newcode:我已经创建了解决此问题的代码。但是,我在NSN网络之上有几个层,包括RestKit。我几乎只是查找401响应,缓存生成401的请求,刷新令牌,然后重试触发401的请求。它变得相当复杂,因为我也可以有并行的请求,并且可以在任何一个请求中获得401。不想在已经进行令牌刷新时进行令牌刷新。patric.schenke的代码会帮你完成大部分任务。