2017-02-14 5 views
2

私のアプリでoauth2トークンをリフレッシュする方法についてのアドバイスが必要です。同じ時間にタスクを実行しないようにする

私はoauth2トークン(1時間後に期限が切れます)で接続されている私のAPIへの私のHTTP要求を行うためにGRPCを使用しています。

すべての要求を起動する前に、私はトークンをチェック:

アップツーデート
  • ?ネットワークリクエストを起動してください

  • 期限が切れていますか? refreshTokenを起動する - > launch networkRequest

すべてがうまくいくようですが、クライアントがトークンを「失う」場合もあります。

問題は、2つの要求を& Bは、トークンが古くなっている場合、彼らはそれを更新します両方、正確に同じ時間にを立ち上げていることです。 私のサーバーはnewTokenAを生成し、それを返し、newTokenBを生成し(newTokenAを削除)、それを返します。 newTokenB の後にnewTokenAがクライアントに到着すると、の後にクライアントのトークントークンが正しく表示されません。

私はセマフォを使用して、同時に1つのrefreshTokenを確実に呼び出すようにしました。

私のセマフォが待っているとき、私のサーバーからの応答はありません。

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

がキューを維持し、誰かが新しいリクエストが付属してカウントは理想的なあなたは既にフェッチされているよりも大きいものであれば、できるだけ早くトークンリフレッシュするための(シリアル要求を実行することができます)(selfはとにかく知られているように見えます)トークンは新しい要求を処理しません。 –

+0

価値があるのは、https://github.com/p2/OAuth2 Swiftフレームワークがあなたのために行うことです(公開:私はレポメンテナです)。 – Pascal

答えて

1

:このような何かを行います読んで、あなたが包み、最後の要求が応答しません、タイムアウトでそれを試してみて、この方法は完全に非同期で作っていないのはなぜ

リターン自己の前に
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

まず、私は(目的を読み取るために使用されている)ではない0ため、1リソースのセマフォを作成することをお勧め:

let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0) 

第二に、私は問題があなたの最初のリリースということだと思いますその後、セマフォ、および完了ブロックを呼び出す:私はあなたのdispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)があなたの目を保持していると思います

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

をそれを置くことができますか?

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()) 
     } 
    } 
} 
関連する問題