用户状态和身份验证

时间:2016-12-19 17:59:32

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

我正在使用此代码使用服务在后台检测我的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) {

    }
});

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

我尝试了多种解决方案,例如添加我的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.

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

1 个答案:

答案 0 :(得分:7)

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

一些可能的解决方法包括:

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

  2. 打开安全规则,以便onDisconnect()。removeValue()无需身份验证即可完成。这显然不太理想。 push-id不容易被其他客户猜测的事实可能意味着有一种方法可以安全地做到这一点,但你必须阻止其他客户端读取/注册用户/ $ uid /(从那以后他们就知道了push-id),可能会破坏你的状态信息的目的。 : - /

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

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

  5. 希望这会给你一些帮助。对不起,这个bug。我们正在寻找客户的解决方案,但我不确定它什么时候会降落。

相关问题