这些是我在 firebase firestore 中的安全规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
这是我的自定义挂钩,用于监听用户身份验证并根据此身份验证进行数据获取:
import { useEffect, useState } from "react";
import { auth } from "./config";
import { onAuthStateChanged } from "firebase/auth";
import { getUserData } from "../actions/userActions";
function useAuth() {
const [user, setUser] = useState<any>(undefined);
const [uid, setUid] = useState<any>(undefined);
const [firstName, setFirstName] = useState<any>(undefined);
const [lastName, setLastName] = useState<any>(undefined);
const [displayName, setDisplayName] = useState<any>(undefined);
const [email, setEmail] = useState<any>(undefined);
const [phone, setPhone] = useState<any>(undefined);
const [address, setAddress] = useState<any>(undefined);
const [role, setRole] = useState<any>(undefined);
useEffect(() => {
const fetchUserData = async (user: any) => {
let userData = await getUserData(user.uid);
if (userData) {
setUid(userData.uid);
setFirstName(userData.firstName);
setLastName(userData.lastName);
setDisplayName(userData.displayName);
setEmail(userData.email);
setPhone(userData.phone);
setAddress(userData.address);
setRole(userData.role);
}
};
const unsubscribe = onAuthStateChanged(auth, (user) => {
if (user) {
setUser(user);
fetchUserData(user);
} else {
setUser(undefined);
setUid(undefined);
setFirstName(undefined);
setLastName(undefined);
setDisplayName(undefined);
setEmail(undefined);
setPhone(undefined);
setAddress(undefined);
setRole(undefined);
}
});
return () => unsubscribe();
});
return {
user,
uid,
firstName,
lastName,
displayName,
email,
phone,
address,
role,
};
}
export default useAuth;
这是“getUserData”函数:
export const getUserData = async (uid: string) => {
try {
const snapshot = await getDoc(doc(firestore, "users", uid));
if (snapshot) return snapshot.data();
else return undefined;
} catch (e) {
console.error("Error at 'getUserData': " + e);
return undefined;
}
};
然后在客户端我只需这样做:
const {user} = useAuth()
并在标签中使用用户对象:
<p>{user.uid}</p>
如果没有设置安全规则,身份验证和数据获取工作正常,但是一旦我设置了规则(如上面的示例),我就会收到错误:
FirebaseError: [code=permission-denied]: Missing or insufficient permissions.
尽管我认为在用户完全登录之前没有数据库提取。
如果我将规则更改为:
allow read, write: if true;
或者
allow read, write: if request.auth == null;
一切都按预期进行。
为什么用户登录时“request.auth”没有正确的值?
令我惊讶的是,您的
getUserData()
方法在某些情况下会返回一些数据,因为使用 DocumentSnapshot
检查 snapshot
(if (snapshot)
对象)不为空应该始终返回 true
。
来自文档:
注意:如果 docRef 引用的位置没有文档, 生成的文档将为空并且调用它上的存在将 返回错误。
您需要按照
文档中的说明使用
if (snapshot.exists())
,即:
export const getUserData = async (uid: string) => {
try {
const snapshot = await getDoc(doc(firestore, "users", uid));
if (snapshot.exists()) return snapshot.data();
else return undefined;
} catch (e) {
console.error("Error at 'getUserData': " + e);
return undefined;
}
};