>我有以下用例按预期工作:
- 新用户到达网站
- 用户会收到匿名登录从 Firebase 获得
user.uid
用户 - 创建一个文档,其作为用户ID引用上述
user.uid
- 在同一页面中,邀请用户登录,否则文档将丢失
- 用户登录并找到帐户文档
赢!
现在我有一个用例无法按预期工作:
- 会话已过期或来自不同浏览器的返回用户到达网站
- 用户通过匿名登录从 Firebase 获得
user.uid
用户 - 创建一个文档,其作为用户 ID 引用上述
user.uid
- 在同一页面中,邀请用户登录,否则文档将丢失
- 用户登录后未找到帐户文档
这次没有赢
:(我使用以下配置配置了火力基础身份验证:
const uiConfig = {
signInFlow: 'popup',
autoUpgradeAnonymousUsers: true,
signInOptions: [
firebase.auth.GoogleAuthProvider.PROVIDER_ID,
],
callbacks: {
signInFailure: (error: any) => {
if (error.code != 'firebaseui/anonymous-upgrade-merge-conflict') {
return Promise.resolve();
}
var cred = error.credential;
return firebase.auth().SignInAndRetrieveDataWithCredential(cred);
}
},
};
因此,如您所见,问题是,第一次,autoUpgradeAnonymousUsers
使用匿名用户ID创建一个新的userId,一切都很好,但是当然第二次不再起作用了。
鉴于在我的安全规则中,我想创建一个检查,userId
无法更新,并且只有具有相同 userId 的请求才能看到文档,我应该如何解决这个问题?
安全规则:
allow create: if request.auth.uid != null
allow read: if request.auth.uid == resource.data.userId
&& request.auth.uid != null
allow update: if request.auth.uid == request.resource.data.userId && resource.data.userId == request.resource.data.userId && request.auth.uid != null
谢谢。
问题是您无法使用相同的凭据创建新用户。如果用户登录,则会丢失匿名登录中的数据。
您必须在本地保存匿名用户的数据,并且在用户登录后,您必须将数据复制到当前用户。您还应该删除匿名帐户。
我找到了这个使用Firebase实时数据库来保存用户数据的示例。
https://github.com/firebase/firebaseui-web#upgrading-anonymous-users
// signInFailure callback must be provided to handle merge conflicts which
// occur when an existing credential is linked to an anonymous user.
signInFailure: function(error) {
// For merge conflicts, the error.code will be
// 'firebaseui/anonymous-upgrade-merge-conflict'.
if (error.code != 'firebaseui/anonymous-upgrade-merge-conflict') {
return Promise.resolve();
}
// The credential the user tried to sign in with.
var cred = error.credential;
// If using Firebase Realtime Database. The anonymous user data has to be
// copied to the non-anonymous user.
var app = firebase.app();
// Save anonymous user data first.
return app.database().ref('users/' + firebase.auth().currentUser.uid)
.once('value')
.then(function(snapshot) {
data = snapshot.val();
// This will trigger onAuthStateChanged listener which
// could trigger a redirect to another page.
// Ensure the upgrade flow is not interrupted by that callback
// and that this is given enough time to complete before
// redirection.
return firebase.auth().signInWithCredential(cred);
})
.then(function(user) {
// Original Anonymous Auth instance now has the new user.
return app.database().ref('users/' + user.uid).set(data);
})
.then(function() {
// Delete anonymnous user.
return anonymousUser.delete();
}).then(function() {
// Clear data in case a new user signs in, and the state change
// triggers.
data = null;
// FirebaseUI will reset and the UI cleared when this promise
// resolves.
// signInSuccessWithAuthResult will not run. Successful sign-in
// logic has to be run explicitly.
window.location.assign('<url-to-redirect-to-on-success>');
});
}