Javascript 如何防止同一用户同时登录Firebase?
我希望新的会话基本上“注销”以前的任何会话。例如,当您在一台计算机上进行身份验证会话时,在另一台计算机上启动新会话并在我们的应用程序上使用firebase进行身份验证将注销第一台计算机上的另一个会话 我还没有找到任何允许我“远程”注销会话的方法。我知道我可以在一个会话中取消对()和goOffline()的访问。但是如何从同一用户的不同身份验证会话中执行此操作 谢谢你的帮助 背景信息:Javascript 如何防止同一用户同时登录Firebase?,javascript,jquery,web-applications,firebase,Javascript,Jquery,Web Applications,Firebase,我希望新的会话基本上“注销”以前的任何会话。例如,当您在一台计算机上进行身份验证会话时,在另一台计算机上启动新会话并在我们的应用程序上使用firebase进行身份验证将注销第一台计算机上的另一个会话 我还没有找到任何允许我“远程”注销会话的方法。我知道我可以在一个会话中取消对()和goOffline()的访问。但是如何从同一用户的不同身份验证会话中执行此操作 谢谢你的帮助 背景信息: 我使用简单的电子邮件/密码登录进行firebase身份验证 我还没有设置安全规则,尽管这正在进行中 我在Fire
一般的想法是,您希望在Firebase中创建一些元数据,它告诉您用户从多少个位置登录。然后,您可以使用此信息限制他们的访问 要做到这一点,您需要生成自己的令牌(以便您的安全规则可以使用这些信息) 1)生成令牌 用于生成您自己的令牌。每个令牌应包含客户端的唯一ID(IP地址?UUID?) 2)使用状态来存储用户的位置id 有关详细信息,请查看底漆:
var fb = new Firebase(URL);
// after getting auth token back from your server
var parts = deconstructJWT(token);
var ref = fb.child('logged_in_users/'+token.id);
// store the user's location id
ref.set(token.location_id);
// remove location id when user logs out
ref.onDisconnect().remove();
// Helper function to extract claims from a JWT. Does *not* verify the
// validity of the token.
// credits: https://github.com/firebase/angularFire/blob/e8c1d33f34ee5461c0bcd01fc316bcf0649deec6/angularfire.js
function deconstructJWT(token) {
var segments = token.split(".");
if (!segments instanceof Array || segments.length !== 3) {
throw new Error("Invalid JWT");
}
var claims = segments[1];
if (window.atob) {
return JSON.parse(decodeURIComponent(escape(window.atob(claims))));
}
return token;
}
3)添加安全规则
在安全规则中,强制只有当前唯一位置可以读取数据
{
"some_restricted_path": {
".read": "root.child('logged_in_users/'+auth.id).val() === auth.location_id"
}
}
4)控制登录用户的写访问权
您需要设置一些系统来控制登录用户的写访问权限。显然,用户只能写入自己的记录。如果希望第一次登录尝试始终获胜,则使用“.write:”!data.exists()“
但是,您可以通过允许最后一次登录获胜来大大简化,在这种情况下,它将覆盖旧的位置值,并且以前的登录将无效并无法读取
5)这不是控制并发数的解决方案
您不能使用此选项来阻止多个并发到您的Firebase。有关实现这一点的更多数据,请参见goOffline()和goOnline()(或获得付费计划,这样您就不会对连接设置硬限制)。TL;DR
我们也遇到过这个话题。尽管这条线索已经过时,而且事实上它并没有完全勾勒出我们想要实现的完全相同的愿望,但是我们可以吸收一些关于“的答案”的一般概念。这些概念大致保持不变,但这条线索绝对值得一个更为最新的答案 注意:在你马上阅读这个解释之前,要意识到这样一个事实:你可能会发现它有点脱离上下文,因为它没有完全涵盖原来的SO问题。事实上,组装一个系统以防止同时进行多个会话是一种完全不同的思维模式。更准确地说,是我们的思维模式适合我们的情景 例如,当您在一台计算机上进行身份验证会话时,在另一台计算机上启动新会话并在我们的应用程序上使用firebase进行身份验证将注销第一台计算机上的另一个会话 维护这种类型的“同时登录预防”意味着1)每个客户端的活动会话应该有所区别,即使它来自同一设备2)客户端应该从AFAICT Firebase无法使用的特定设备注销。FWIW您可以显式地使指定用户的所有刷新令牌过期,因此系统会提示您再次登录,但这样做的缺点是会破坏所有现有会话(即使是刚刚激活的会话) 这些“间接费用”导致以稍微不同的方式处理问题。它的不同之处在于1)无需跟踪具体设备2)客户端以编程方式注销,而不会不必要地破坏其任何活动会话以增强用户体验
利用这一点来完成跟踪客户端连接状态更改的繁重任务(即使连接因某种奇怪的原因而终止),但这里有一个问题:Firestore并不是本机提供的。请参阅以保持数据库同步。值得注意的是,与他们的示例相比,我们没有设置对特殊路径的引用。相反,我们利用观察者来响应身份验证状态的变化
const getUserRef=userId=>firebase.database().ref(`/users/${userId}`);
firebase.auth().onAuthStateChanged(用户=>{
如果(用户){
constuserref=getUserRef(user.uid);
返回userRef
.onDisconnect()文件
.设置({
你在线吗:错,
最后一次看到:firebase.database.ServerValue.TIMESTAMP
})
.然后(()=>
//一旦将`onDisconnect()`附加到用户的ref,这会将标志设置为true。
userRef.set({
你是在线的吗,
最后一次看到:firebase.database.ServerValue.TIMESTAMP
});
);
}
});
正确设置onDisconnect()
后,如果用户尝试在另一个活动会话旁边启动登录,则必须确保该用户的会话,为此,将请求转发到数据库并对照相应的标志进行检查。因此,由于这种额外的往返过程,识别多个会话比通常要花费更多的时间,因此应该相应地调整UI
const ensureUserSession=userId=>{
const userRef=getUserRef(userId);
返回userRef.one(“值”)。然后(快照=>{
如果(!snapshot.exists()){
//如果用户条目没有
{
"some_restricted_path": {
".read": "root.child('logged_in_users/'+auth.id).val() === auth.location_id"
}
}