2017-02-14 82 views
2

我需要关于如何处理在我的应用中刷新的oauth2令牌的建议。防止同时执行任务

我正在使用GRPC将我的http请求发送到我使用oauth2令牌连接的API(它在1小时后过期)。

发动每一个请求之前,我检查令牌:

  • 截至到最新的吗?发射网络请求

  • 过期?推出refreshToken - >推出networkRequest

一切似乎运作良好,但在某些情况下,我的客户“丢失”的标记。

问题是,对于2个请求A & B推出在完全相同的时间,如果令牌已过时,他们都会刷新它。 我的服务器将生成一个newTokenA,返回它,生成newTokenB(删除newTokenA),并返回它。 如果响应newTokenA在newTokenB之后到达客户端,则客户令牌令牌将不是好的。

我用了一个信号量来确保一次调用refreshToken是在同一时间完成的。

但是当我的Semaphore正在等待时,我没有收到我的服务器的任何响应。

let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0) 

func authenticate(completion: (GRPCProtoCall) -> (Void)) -> GRPCProtoCall { 

    // Wait here if authenticate already called 
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) 

    // If token up to date 
    if isOAuth2TokenValid() { 
     dispatch_semaphore_signal(semaphore) // Release semaphore 
     completion(self.withAuthorization()) 
     return self 
    } 

    // Refresh the outdated token 
    APIClient.shared.oAuth2AccessTokenRefresh { (response) -> (Void) in 
     dispatch_semaphore_signal(semaphore) // Release semaphore 
     completion(self.withAuthorization()) 
    } 

    return self 
} 
+0

保持队列中有人使用了新的要求,尽快(可串行执行的请求)的令牌清爽,如果计数大于一个理想,你已经获取了令牌因此不处理新的请求。 –

+0

对于它的价值,https://github.com/p2/OAuth2 Swift框架将为您做到这一点(披露:我是回购维护者)。 – Pascal

回答

1

我觉得你dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)抱着你的日阅读,你可以用超时柜面最后的请求不响应尝试它,并把它归还之前自

while semaphore.wait(timeout: DispatchTime.now() + Double(5000000000)/Double(NSEC_PER_SEC)) == DispatchTimeoutResult.success {//time out set to 5 seconds 
    print("wait") 
} 
+0

感谢您的帮助,信号量持有线程,然后,此线程无法从我的服务器收到任何响应! – Toldy

0

首先,我建议创建信号灯为1资源,而不是0(这是用于阅读目的):

let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0) 

其次,我认为这个问题是你首次发布信号量,然后调用完成块:做这样的事情:

// Refresh the outdated token 
APIClient.shared.oAuth2AccessTokenRefresh { (response) -> (Void) in 
    completion(self.withAuthorization()) 
    dispatch_semaphore_signal(semaphore) // Release semaphore at very end 
} 
0

为什么不制作方法完全异步? (self似乎反正知道)

func authenticate(completion: (GRPCProtoCall) ->()) { 

    // If token up to date 
    if isOAuth2TokenValid() { 
     completion(self.withAuthorization()) 
    } else { 
    // Refresh the outdated token 
     APIClient.shared.oAuth2AccessTokenRefresh { response in 
      completion(self.withAuthorization()) 
     } 
    } 
}