将 Firebase 身份验证与 Firestore 一起使用的正确方法是啥?
Posted
技术标签:
【中文标题】将 Firebase 身份验证与 Firestore 一起使用的正确方法是啥?【英文标题】:What's the proper way to use Firebase Authentication along with Firestore?将 Firebase 身份验证与 Firestore 一起使用的正确方法是什么? 【发布时间】:2021-07-04 09:02:17 【问题描述】:大家好 - 我正在使用 Next.js 和 Firebase 构建一个应用程序,这两种技术对我来说都是全新的。这是一个简单的应用程序,用户创建一个帐户并且必须登录。如果用户不创建一个帐户,该应用程序将毫无用处——他们无法进入下一个屏幕,即仪表板。无论如何,当他们登录时,他们就可以创建旅行/度假行程。我将 Firebase Auth 用于身份验证,并将 Firestore(不是实时数据库)用作我的数据库。我的目标是,当用户登录时,用户可以看到他们创建的每个行程,而没有其他人的。它应该是完整的 CRUD。这也是我第一次进行这种身份验证,所以这可能会增加我的困惑。
我知道我的代码不正确,但它确实有效。不断发生的是,用户登录和注销时似乎存在延迟。我已经在本地副本上对此进行了测试。当我注销然后以其他用户身份重新登录时,它告诉我 uid 为空。 1 到 30 分钟后(严重),页面突然加载了我登录时使用的 uid!我读过的所有内容都表明身份验证存在延迟,但除了指出问题之外,我真的找不到解决方案——所以基本上写了一个控制台日志,说明当时谁登录了,然后同样当他们注销时。另外,我观看/阅读了大量教程,所以也许这是我的代码?对于这部代码小说,我提前感到非常抱歉——我会尽我所能组织起来!
这是我的配置信息,所以我将 Firebase 称为火。登录方法是电子邮件和密码,就在身份验证屏幕上捕获该信息而言,一切在 Firebase 中看起来都应该如此。
import firebase from 'firebase';
const firebaseConfig =
apiKey: 'AIzaSyB-xEPETXSfjboKe5H0kPUu-ZdRDGfszmA',
authDomain: "where-to-jess.firebaseapp.com",
databaseURL: 'https://where-to-jess-default-rtdb.firebaseio.com/',
projectId: "where-to-jess",
storageBucket: "where-to-jess.appspot.com",
messagingSenderId: "914509599583",
appId: "1:914509599583:web:80cdf3e4090417b0f35cea"
;
try
firebase.initializeApp(firebaseConfig);
catch(err)
if (!/already exists/.test(err.message))
console.error('Firebase initialization error', err.stack)
const fire = firebase;
export default fire;
当用户创建帐户时,他们也会被添加到我的数据库中的集合“用户”中。我也在使用 React Hooks(第一次)。他们的电子邮件是他们登录的用户名,但我正在数据库中捕获他们的电子邮件。他们也会在创建帐户后立即登录。这部分也有效。
const handleSubmit = (e) =>
e.preventDefault();
setPassword('');
fire.auth().createUserWithEmailAndPassword(userName, password)
.then(() =>
fire.firestore().collection('users').doc(fire.auth().currentUser.uid)
.set(
firstName: firstName,
lastName: lastName,
email: userName
)
.catch(error =>
console.log('user wasn\'t added to db: ', error);
)
)
.catch(error =>
console.log('user wasn\'t able to create an account: ', error);
)
router.push('/users/dashboard')
;
这是我的登录代码:
const handleLogin = (e) =>
e.preventDefault();
fire.auth()
.signInWithEmailAndPassword(username, password)
.catch((error) =>
console.log('user wasn\'t able to login: ', error);
)
setUsername('')
setPassword('')
router.push('/users/dashboard')
;
现在是有趣的部分!这是我的行程表单提交代码。我在这里想要实现的是将这个新创建的行程附加到他们在“用户”数据库中的 uid。我省略了所有表单内容,因为它超长。这似乎也有效——无论我使用哪个帐户,我都可以在数据库中看到它。
const handleSubmit = (e) =>
e.preventDefault();
fire.firestore()
.collection('users').doc(fire.auth().currentUser.uid).collection('itineraries')
.add(
//
)
.catch(error =>
console.log('itinerary not added to db ', error)
)
router.push('/users/dashboard')
这就是它发生的地方!我怀疑这是因为我在偷工减料,我将在下面解释。此仪表板应仅显示当前登录用户创建的行程。如果当前登录的用户没有创建任何行程,我会收到一个错误,说 uid 为空。所以,我的解决方法是在他们帐户的数据库中手动创建一个假行程(因为我正在测试)并将 tripName 值设为空。这似乎可行,但这就是奇怪的登录/注销事情发生的地方。
export default function Dashboard()
const router = useRouter();
const [itineraries, setItineraries] = useState([]);
const [loggedIn, setLoggedIn] = useState(false);
fire.auth()
.onAuthStateChanged((user) =>
if (user)
console.log(user.email + " is logged in!");
setLoggedIn(true)
else
setLoggedIn(false)
console.log('User is logged out!');
)
useEffect(() =>
const unsubscribe =
fire.firestore()
.collection('users').doc(fire.auth().currentUser.uid).collection('itineraries').where('tripName', '!=', 'null')
.onSnapshot(snap =>
const itineraries = snap.docs.map(doc => (
id: doc.id,
...doc.data()
));
setItineraries(itineraries);
return () =>
unsubscribe();
;
);
, []);
const handleLogout = () =>
fire.auth()
.signOut()
router.push('/')
;
最后,这是我在 db 上的一条规则。我在阅读规则文档时感到困惑,我觉得我在这里偷工减料。
rules_version = '2';
service cloud.firestore
match /databases/database/documents
match /document=**
allow read
allow write
再次,我真的很抱歉所有这些代码。这是我第一次使用 React Hooks、Next 和 Firebase——所以它是 Firebases 的文档、教程和我自己的代码的混搭。如有任何帮助或建议,我将不胜感激。
【问题讨论】:
【参考方案1】:该规则将允许所有访问当前数据库中的所有文档。你想要这样的东西:
rules_version = '2';
service cloud.firestore
match /databases/database/documents
match /users/user_id
allow read, write: if request.auth != null && request.auth.uid == user_id;
这将只允许经过身份验证的用户访问
【讨论】:
非常感谢 - 如此基本的事情!这就是我尝试同时学习下一个、firebase 和 hooks 的结果......结合重新排序我上面的代码完全解决了这个问题。我没有将 useEffect 或 onAuthStateChanged 放在正确的位置。 Firebase 可能很难上手,我仍然每天都在学习更多。坚持不懈,你的果实终会开花结果:)【参考方案2】:这是我 100% 的用户错误,但我想分享一下,因为我的一些问题似乎很常见。除了上述 AspiringApollo 的建议外,我的功能完全失灵(正如我所提到的,钩住新手)。上面加上像这样构造我的函数修复了它:
useEffect(() =>
const unsubscribe =
fire.auth()
.onAuthStateChanged((user) =>
if (user)
let uid = user.uid
console.log(user.email + ' is logged in!');
setLoggedIn(true)
// all the things you want to do while the user is logged in goes here
else
setLoggedIn(false)
console.log('user is logged out!');
return () =>
unsubscribe();
;
);
, []);
仍然愿意接受建议和更多的目光,因为我知道这有点混乱!
【讨论】:
以上是关于将 Firebase 身份验证与 Firestore 一起使用的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Google Play 游戏登录与 Firebase 身份验证结合使用
将 Google 身份验证令牌与 Firebase 一起使用
将 Firebase 身份验证与新的 @App 协议一起使用
将 Firebase 身份验证与 Firestore 一起使用的正确方法是啥?