2017-02-14 92 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()) 
     } 
    } 
}