4

我試圖驗證由Android中的Firebase認證庫在GCE端點中創建的客戶端令牌。Google Cloud Endpoint在端點執行異步代碼

的如何做到這一點的引導可以發現here

基本上我需要調用從終點(即服務器後端代碼不機器人碼)此代碼段。

FirebaseAuth.getInstance().verifyIdToken(idToken) 
    .addOnSuccessListener(new OnSuccessListener<FirebaseToken>() { 
     @Override 
     public void onSuccess(FirebaseToken decodedToken) { 
      String uid = decodedToken.getUid(); 
      // ... 
     } 
}); 

讓我們說,我想執行的代碼,並返回用戶的Android客戶端代碼。我應該怎麼做?

這是我沒有意義的示例代碼。但它展現了我想要做的!

@ApiMethod(name = "serverAuth") 
public MyUser serverAuth(@Named("token") String token) { 
    FirebaseAuth.getInstance().verifyIdToken(token) 
      .addOnSuccessListener(new OnSuccessListener<FirebaseToken>() { 
       @Override 
       public void onSuccess(FirebaseToken decodedToken) { 
        String uid = decodedToken.getUid(); 
        String email = decodedToken.getEmail(); 
        String name = decodedToken.getName(); 
        Map<String, Object> claims = decodedToken.getClaims(); 

        String claimString = ""; 

        for (Object claim : claims.values()) { 
         claimString += claims.toString(); 
        } 

        MyUser user = new MyUser(uid, email, name, claimString); 
        //How to return this user? 

       } 
      }); 

    //This is compile error since user varriable does not exist here  
    return user; 

} 

我有谷歌搜索如何在GCE端點執行異步代碼。但沒有得到。我得到的是關於代碼執行的東西,它直到完成才阻塞,然後返回用戶。但是,如何編寫代碼以便上述異步代碼被阻塞?

回答

4

CountDownLatch是你需要的魔法類。它會讓你等到OnSuccessListener實際完成。

適應你的方法是這樣的:(我刪除導致MYUSER的創作以關注重要點的步驟。)

@ApiMethod(name = "serverAuth") 
public MyUser serverAuth(@Named("token") String token) { 
    final List<MyUser> users = new ArrayList<>(); 
    final CountDownLatch cdl = new CountDownLatch(1); 
    FirebaseAuth.getInstance().verifyIdToken(token) 
      .addOnSuccessListener(new OnSuccessListener<FirebaseToken>() { 
       @Override 
       public void onSuccess(FirebaseToken decodedToken) { 
        // ... init uid, email, name and claimString 
        users.add(new MyUser(uid, email, name, claimString)); 
        cdl.countDown(); 
       } 
      }); 
    try { 
     cdl.await(); // This line blocks execution till count down latch is 0 
    } catch (InterruptedException ie) { 

    } 
    if (users.size() > 0) { 
     return users.get(0); 
    } else { 
     return null ; 
    } 
} 

這是你所需要的基本版本。恕我直言,這需要2點更多的改進:

  • 你也應該採取可能失敗的考慮:

    FirebaseAuth.getInstance().verifyIdToken(token) 
    .addOnSuccessListener(new OnSuccessListener<FirebaseToken>() { 
        @Override 
        public void onSuccess(FirebaseToken decodedToken) { 
         cdl.countDown(); 
        } 
    }).addOnFailureListener(new OnFailureListener() { 
        @Override 
        public void onFailure(@NonNull Exception e) { 
         // log error, ... 
         cdl.countDown(); 
        } 
    }); 
    
  • 你也應該採取沒有聽衆被稱爲可能性。在這種情況下,你的方法永遠不會返回。爲了避免這種情況,你可以在的await()方法設置一個超時

    try { 
        // This line blocks execution till count down latch is 0 
        // or after 30 seconds. 
        cdl.await(30l, TimeUnit.SECONDS); 
    } catch (InterruptedException ie) { 
    
    } 
    

就是這樣。希望這可能有所幫助。

+0

謝謝!有用。但是,我得到錯誤,用戶變量是最終的,不能設置。我通過將用戶提升爲類私有變量來解決此問題。這僅僅是一個測試代碼,因此可以被混淆。但是我仍然有興趣瞭解一個更好的方法來做用戶變量作爲最終變量。 –

+0

是的,你是對的 - 禁止分配最終變量。對不完整的測試樣本。但我認爲使用類變量並不是最好的解決方法。我寧願使用「容器」或「包裝器」。看到我更新的答案。 – Benoit