Objective c 使用Reactivecocoa刷新OAuth令牌

Objective c 使用Reactivecocoa刷新OAuth令牌,objective-c,reactive-cocoa,Objective C,Reactive Cocoa,所以我想做的就是这样 发出包含指定授权令牌的标头的HTTP请求 如果响应是401 Unauthorized,我希望使用我的刷新令牌获取新的访问令牌和新的刷新令牌 当我拥有新的令牌对时,我希望使用新的令牌重试失败的请求 我看了这篇文章就知道了。他们是这样解决的 - (RACSignal *)doRequestAndRefreshTokenIfNecessary:(RACSignal *)requestSignal { return [requestSignal catch:^(NSEr

所以我想做的就是这样

  • 发出包含指定授权令牌的标头的HTTP请求
  • 如果响应是401 Unauthorized,我希望使用我的刷新令牌获取新的访问令牌和新的刷新令牌
  • 当我拥有新的令牌对时,我希望使用新的令牌重试失败的请求
我看了这篇文章就知道了。他们是这样解决的

    - (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;
}
-(RACSignal*)刷新令牌{
NSDictionary*参数=@{
@“客户端id:[Config clientId],
@“客户端密码”:[Config clientSecret],
@“授权类型”:@“刷新”,
@“刷新令牌”:[[Tokens sharedTokens]刷新令牌]
};
if(self.activeRefreshSignal==nil){
@weakify(自我)
self.activeRefreshSignal=[RACSignal createSignal:^RACDisposable*(id订户){
@强化(自我)
[[RestAPI sharedClient]POST:@/oauth/token”
参数:params
成功:^(NSURLSessionDataTask*操作,id responseObject){
[从responseObject:responseObject中自提取令牌];
[用户发送下一步:无];
[用户发送完成];
self.activeRefreshSignal=nil;
}
失败:^(NSURLSessionDataTask*操作,NSError*错误){
[[Tokens sharedTokens]clearTokens];
[订户发送错误:错误];
self.activeRefreshSignal=nil;
}];
返回零;
}];
}
返回自激活刷新信号;
}

有没有办法避免比赛状态,只刷新一次

你有没有找到解决这个问题的办法,安德烈亚斯?