我有一个使用firebase auth和firebaseUI进行身份验证的项目。我已经启用了Google,Facebook和电子邮件提供商。我需要的是远程注销或禁用某些用户。
我希望用户这样做退出应用程序。我尝试在Firebase控制台中禁用用户,还使用Firebase管理SDK(https://firebase.google.com/docs/auth/admin/manage-sessions)撤消刷新令牌。
我等待了2天以上,但仍然注意到该用户已登录并且可以访问Firestore数据。
我也经历了尝试 Firebase still retrieving authData after deletion
谁能指出我做错了什么?
答案 0 :(得分:4)
您也不能远程强制用户注销。任何注销都必须从用户登录的设备上进行。
一旦铸造出访问令牌,就无法撤消它。这意味着,即使您禁用了该用户的帐户,他们也可能继续拥有长达一个小时的访问权限。
如果时间太长,诀窍(正如我对所链接问题的回答中所提到的)是维护数据库(或其他位置)中被阻止用户的列表,然后根据安全规则(或其他授权层)。
例如,在实时数据库中,您可以创建被阻止用户的UID的列表:
banned_uids
uid1: true
uid2: true
然后使用以下命令检查您的安全规则中的内容:
".read": "auth.uid !== null && !root.child('banned_uids').child(auth.uid).exists()"
答案 1 :(得分:4)
您可以使用FCM发送消息数据以强制注销。
例如,如果用户使用android应用程序。
成功!
答案 2 :(得分:2)
根据您的情况,我假设您在禁用用户时需要注销用户。
使用一个全局变量存储 TokenNo (可能处于共享首选项或sqlite):
在清单中添加以下代码:
<service android:name=".YourFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
在您的
中添加以下代码public class LogoutOntokenchange extends FirebaseMessagingService{
@Override
public void onNewToken (String token){
if(TokenNo=>1){ //if tokenNo >=1 means he already logged in
TokenNo=0;
FirebaseAuth.getInstance().signOut(); //Then call signout method
}
else{
TokenNo=1; //store token no in db
}
}
}
这里发生的事情:
当用户首次登录时,调用onNewToken时,它将进入其他位置,然后TokenNo从0更新为1。
当您禁用任何用户时,令牌将自动刷新。然后调用OnNewToken,然后TokenNo> = 1,因此用户将被注销。
注意::当用户首次登录时,即如果未存储TokenNo变量,则将其存储为0。
供参考:https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService
答案 3 :(得分:0)
尚未进行测试,因为负责设置Firestore规则的后端程序员今天已经不在了,但从理论上讲这应该可行:(这是我明天要测试的东西)
具有一个FirebaseAuth.AuthStateListener负责根据用户的状态提供用户界面
这结合了Firestore中的规则
match /collection
allow read: if isAuth();
isAuth在哪里:
function isAuth() {
return request.auth.uid != null;
}
如果随后在登录时禁用了用户,则每当用户尝试从集合中读取数据时,都应拒绝该用户,并应进行signOut()调用。 然后,AuthStateListener将对其进行检测,然后将用户注销。
答案 4 :(得分:0)
我能想到的唯一方法是在开始活动中添加if-else块。 将用户的状态(已验证/禁止/删除)存储在Firebase实时数据库中。然后在应用程序启动时获取用户状态并添加代码:
if (currentUserStatus.equals("banned"))
{
currentUser.logout();
}
答案 5 :(得分:0)
我要做的是在为每个用户注册一个以UID作为文档ID的Firestore文档时创建的。在本文档中,我存储一个数组,该数组存储单个用户登录到新设备时收到的所有fcm令牌。这样,我将始终跟踪用户的登录位置。当用户手动注销时,fcm令牌将从Firestore中以及设备上的文档中删除。
为了能够在用户登录的任何地方注销该用户,我执行了以下操作。启动应用程序后,一旦用户登录,我就启动一个快照侦听器,该侦听器侦听用户文档中的所有更改。进行更改后,我将立即检索新的fcm令牌数组,在该数组内搜索本地当前设备的fcm令牌。如果找到,我什么也不做。如果fcm令牌不再存在于数组中,我将调用本地注销方法,然后返回登录屏幕。
以下是我在iOS上快速使用的方法。闭包(passOnMethod)只会触发对登录视图控制器的放松选择。
import Foundation
import Firebase
class FB_Auth_Methods {
let db = Firestore.firestore()
var listener: ListenerRegistration?
func trackLoginStatus(passOnMethod: @escaping () -> () ) {
listener?.remove()
if let loggedInUserA_UID = Auth.auth().currentUser?.uid {
listener = db.collection(K.FStore.collectionOf_RegisteredUsers_Name)
.document(loggedInUserA_UID)
.addSnapshotListener { (snapshotDocument, error) in
if let error = error {
print(error)
} else {
if let document = snapshotDocument {
if let data = document.data() {
if let fcmTokens = data[K.FStore.Users.fcmTokens] as? [String] {
print("Found the following tokens: \(fcmTokens)")
self.compareTokensAgainstCurrentDeviceToken(fcmTokens: fcmTokens, passOnMethod: { () in
passOnMethod()
})
}
}
}
}
}
}
}
func compareTokensAgainstCurrentDeviceToken(fcmTokens: [String], passOnMethod: @escaping () -> () ) {
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print(error)
} else if let result = result {
if fcmTokens.contains(result.token) {
print("Token found, doing nothing")
} else {
print("Token no longer found, logout user")
do {
try Auth.auth().signOut()
InstanceID.instanceID().deleteID { error in
if let error = error {
print(error)
} else {
passOnMethod()
}
}
} catch let signOutError as NSError {
print (signOutError)
}
}
}
}
}
}
这是我在当前设备上各处注销用户时使用的方法。
func deleteAllFcmTokensExceptCurrent(loggedInUserA: User, passOnMethod: @escaping () -> () ) {
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print(error)
} else if let result = result {
let batch = self.db.batch()
let deleteAllFcmRef = self.db.collection(K.FStore.collectionOf_RegisteredUsers_Name).document(loggedInUserA.uid)
batch.updateData([K.FStore.Users.fcmTokens: FieldValue.delete()], forDocument: deleteAllFcmRef)
let updateFcmTokenRef = self.db.collection(K.FStore.collectionOf_RegisteredUsers_Name).document(loggedInUserA.uid)
batch.updateData([K.FStore.Users.fcmTokens: FieldValue.arrayUnion([result.token])], forDocument: updateFcmTokenRef)
batch.commit { (error) in
if let error = error {
print(error)
} else {
passOnMethod()
}
}
}
}
}