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