使用Reactivecocoa刷新OAuth令牌

时间:2014-09-08 18:23:44

标签: objective-c reactive-cocoa

所以我要做的就是这个。

  • 发出HTTP请求,包括指定授权令牌的标头。
  • 如果响应是401 Unauthorized,我希望使用我的刷新令牌获取新的访问令牌和新的刷新令牌。
  • 当我有新的令牌对时,我希望使用新的令牌重试失败的请求。

我通过查看this文章来完成这项工作。他们这样解决了。

    - (RACSignal *)doRequestAndRefreshTokenIfNecessary:(RACSignal *)requestSignal {
return [requestSignal catch:^(NSError *error) {
    // Catch the error, refresh the token, and then do the request again.
    BOOL hasRefreshToken = [UserManager sharedInstance].refreshToken != nil;
    BOOL httpCode401AccessDenied = error.code == -1011;
    if (httpCode401AccessDenied && hasRefreshToken) {
        return [[[self refreshToken] ignoreValues] concat:requestSignal];
    }
    return requestSignal;
}];
}

但这是抓住了。如果我使用过期的访问令牌触发多个请求,我有时会遇到有多次刷新的竞争条件。

所以我认为我可以将刷新信号保存为实例变量,并将所有后续失败的请求“链接”到该变量。但结果是刷新信号多次完成。

- (RACSignal *) refreshToken {
NSDictionary *params = @{
                         @"client_id": [Config clientId],
                         @"client_secret": [Config clientSecret],
                         @"grant_type": @"refresh",
                         @"refresh_token": [[Tokens sharedTokens] refreshToken]
                         };

if (self.activeRefreshSignal == nil) {
    @weakify(self)
    self.activeRefreshSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        @strongify(self)
        [[RestAPI sharedClient] POST:@"/oauth/token"
                                 parameters:params
                                    success:^(NSURLSessionDataTask *operation, id responseObject) {
                                        [self extractTokensFromResponseObject:responseObject];
                                        [subscriber sendNext:nil];
                                        [subscriber sendCompleted];
                                        self.activeRefreshSignal = nil;
                                    }
                                    failure:^(NSURLSessionDataTask *operation, NSError *error) {
                                        [[Tokens sharedTokens] clearTokens];
                                        [subscriber sendError:error];
                                        self.activeRefreshSignal = nil;
                                    }];
        return nil;
    }];
}

return self.activeRefreshSignal;
}

任何想法如何避免竞争条件,只做一次刷新?

0 个答案:

没有答案