【问题标题】:User Presence and Authentication用户存在和身份验证
【发布时间】:2016-12-19 17:59:32
【问题描述】:

我正在使用此代码在后台使用服务检测我的 Android 应用中的用户存在:

final FirebaseAuth mAuth = FirebaseAuth.getInstance();
final FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myConnectionsRef = database.getReference("connected-users").child(mAuth.getCurrentUser().getUid());
final DatabaseReference lastOnlineRef = database.getReference("/registered-users/").child(mAuth.getCurrentUser().getUid()).child("/lastOnline");
final DatabaseReference connectedRef = database.getReference(".info/connected");

connectedRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot snapshot) {
        boolean connected = snapshot.getValue(Boolean.class);
        if (connected) {
            DatabaseReference con = myConnectionsRef.push();
            lastOnlineRef.onDisconnect().setValue(ServerValue.TIMESTAMP);
            con.onDisconnect().removeValue();
            con.setValue(Boolean.TRUE);


            Log.i("CONNECTED", "true");

        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

问题似乎是每隔一小时,根据我的发现,身份验证令牌会再次检索,在此期间,它会在节点中创建一个新条目,显示用户已连接。该条目不会被删除,从而创建了一个幽灵用户。

我尝试了多种解决方案,例如添加我的 SHA1 密钥和使用新的 google-services.json 文件到我的项目中,但收效甚微。似乎问题在于身份验证,因为当我从数据库中删除身份验证规则时,这不再发生。

这里有一些显示问题的日志:

I/art: Enabling alloc tracker (65536 entries of 16 frames, taking 8MB)
W/PersistentConnection: pc_0 - Auth token revoked: expired_token (Auth token is expired.)
D/EventRaiser: Raising 1 event(s)
D/EventRaiser: Raising /.info/connected: VALUE: false
D/Persistence: Starting transaction.
D/Persistence: Persisted a total of 1 rows and deleted 0 rows for a set at /registered-users/....../lastOnline in 2ms
D/Persistence: Transaction completed. Elapsed: 38ms
D/RepoOperation: Aborting transactions for path: /registered-users/....../lastOnline. Affected: /registered-users/....../lastOnline
D/Persistence: Starting transaction.
D/Persistence: Persisted a total of 1 rows and deleted 1 rows for a set at /connected-users/....../-KZLNBlImkX978ftO6z1 in 2ms
D/Persistence: Transaction completed. Elapsed: 6ms
D/RepoOperation: Aborting transactions for path: /connected-users/....../-KZLNBlImkX978ftO6z1. Affected: /connected-users/....../-KZLNBlImkX978ftO6z1
W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
D/FirebaseAuth: Notifying listeners about user ( ...... ).
D/FirebaseApp: Notifying auth state listeners.
D/FirebaseApp: Notified 1 auth state listeners.
D/RepoOperation: Auth token changed, triggering auth token refresh
D/EventRaiser: Raising 1 event(s)
D/EventRaiser: Raising /.info/connected: VALUE: true
I/CONNECTED: true
D/RepoOperation: set: /connected-users/....../-KZLTZmyGMvWPdJKmdeV
D/DataOperation: set: /connected-users/....../-KZLTZmyGMvWPdJKmdeV true
D/Persistence: Starting transaction.
D/Persistence: Persisted user overwrite in 1ms
D/Persistence: Transaction completed. Elapsed: 8ms
D/RepoOperation: Aborting transactions for path: /connected-users/....../-KZLTZmyGMvWPdJKmdeV. Affected: /connected-users/....../-KZLTZmyGMvWPdJKmdeV
D/Persistence: Starting transaction.
D/Persistence: Deleted 1 write(s) with writeId 2 in 1ms
D/Persistence: Persisted a total of 1 rows and deleted 0 rows for a set at /connected-users/....../-KZLTZmyGMvWPdJKmdeV in 7ms
D/Persistence: Transaction completed. Elapsed: 34ms
W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.

我的初始身份验证是通过自定义令牌进行的。

【问题讨论】:

    标签: android firebase firebase-realtime-database firebase-authentication


    【解决方案1】:

    您的理解完全正确。我们正在努力对 SDK 进行更改以缓解此问题,但目前存在一个问题,即当您的身份验证令牌过期时,我们最终会使用新令牌重新连接到数据库,但由于旧的身份验证令牌已经过期,您的来自重新连接的 onDisconnect() 操作未经身份验证执行,因此可能会失败。

    一些潜在的解决方法包括:

    1. 您可以在 60 分钟到期之前手动强制刷新令牌。您可以通过定期调用FirebaseAuth.getInstance().getCurrentUser().getToken(true) 来做到这一点。我们将自动将新令牌与数据库一起使用,因此旧令牌不会过期。

    2. 打开您的安全规则,以便 onDisconnect().removeValue() 无需身份验证即可完成。这显然不理想。其他客户端不容易猜到 push-id 的事实可能意味着有一种方法可以安全地执行此操作,但您必须阻止其他客户端读取 /registered-users/$uid/ (从那时起他们就会知道push-id),这可能会破坏您的存在信息的目的。 :-/

    3. 您可以让客户端记住它的“旧”推送 ID,并在重新连接后将其删除(尽管如果客户端 真的 在重新连接之前消失,仍然存在潜在的竞争条件。

    4. 您可以编写客户端以自动检测/删除陈旧的存在条目(例如,基于时间戳)。

    希望这能给你一些帮助。对不起这个错误。我们正在对客户端进行修复,但我不确定它何时会落地。

    【讨论】:

    • 我已经做了很多选项(4),我认为它运作良好。我没有为每个连接推送 TRUE,而是推送当前令牌的到期时间。我仍然尝试使用 onDisconnect 将其删除,但如果失败,如果时间戳是过去,您仍然可以判断任何给定的连接已过时。它还会在适当的时候发现并删除旧的时间戳。比我希望的要复杂,但它确实有效。
    • 是否有问题提交到某个地方,我们可以在 SDK 中解决问题时收到通知? (我主要关心的是 JS 客户端库,虽然听起来 Android 库也有同样的问题。)
    • 除了这些选项之外,有没有一种干净的方法来处理这个迈克尔?
    • @aldel 你能用代码发布一个可行的解决方案吗?谢谢!
    • @Johnny 对不起,我的代码很复杂,而且我不能合法地在这里发布。但是我的印象是令牌过期问题现在已经解决了,所以问题中的代码现在可以工作了。如果我们能从 Firebase 团队那里得到一些澄清,那就太好了。
    猜你喜欢
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    • 2017-03-06
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    相关资源
    最近更新 更多