所以,我一直在努力解决这个错误......让我先解释一下我的情况:
这些是我的 Firebase 存储规则:
rules_version = "2";
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
// allow read, update, create: if true;
// allow read, write: if request.auth != null;
allow read, create, update: if request.auth != null;
}
}
}
这是我上传图片时的代码:
async saveGuestSignature(signature: string) {
const commonStore = useCommonStore();
const authStore = useAuthStore();
const storageRef = ref(storage, `/guests-signatures/${commonStore.hotel}/${authStore.uid}.png`);
const b64 = signature.substring(signature.indexOf(',') + 1);
try {
const snapshot = await uploadString(storageRef, b64, 'base64');
return await getDownloadURL(snapshot.ref)
} catch (error) {
await saveErrorLog(commonStore.hotel, authStore.uid, 'saveSignature', error);
Notify.create({
type: 'negative',
timeout: 15000,
icon: 'mdi-alert',
message: `Un error sucedió al intentar guardar la firma: ${error}`,
actions: [
{
label: 'Ok',
color: 'white',
handler: () => {
/* ... */
}
}
]
});
return null;
}
},
commonStore.hotel
和 authStore.uid
确实已定义,并且在执行此上传操作之前用户肯定经过身份验证。
大多数情况下,它有效,但对于某些用户,我会随机收到此错误:
FirebaseError:权限缺失或不足。
如您所见,此函数上传图像(base64 字符串)并返回 downloadURL,或者如果失败,则应返回 null,以便将其保存到数据库。
我尝试过更改规则,似乎如果将
read, write: true
设置为允许所有读写操作,它就可以工作,但这显然不是这个想法。
我知道这似乎可能是一个身份验证问题,但是,我很确定用户已通过身份验证,因为例如对 firestore 数据库有更多操作,这也需要用户进行身份验证并且这些操作完美。
添加更多上下文:
这是我验证用户身份的方式:
async doLogin(email: string, password: string) {
const guestStore = useGuestStore();
const commonStore = useCommonStore();
Loading.show({
message: t('login.loadingMsg'),
});
try {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
this.uid = userCredential.user.uid;
this.isAuthenticated = true;
Sentry.setUser({ id: this.uid, email: email });
await guestStore.getUserDataOnce(userCredential.user.uid);
await commonStore.getHotelRules()
const checkInIsDone = guestStore.userData.checkinIsDone;
Loading.hide();
if (checkInIsDone) {
this.router.push({name: 'dashboard'})
} else {
this.router.push({name: 'checkin'})
}
} catch (e:any) {
Loading.hide();
// await saveErrorLog(commonStore.hotel, this.uid, 'doLogin', e);
let message = '';
switch (e.code) {
case 'auth/wrong-password':
message = t('auth.wrong_password');
break;
case 'auth/user-not-found':
message = t('auth.user_not_found');
break;
case 'auth/user-disabled':
message = t('auth.user_disabled');
break;
default:
message = t('general.error', { errorMessage: e });
}
Notify.create({
type: 'negative',
icon: 'mdi-alert',
message: message,
actions: [
{
label: t('general.ok'),
color: 'white'
},
],
});
}
},
onBeforeMount(async () => {
onAuthStateChanged(auth, async (user) => {
authStore.isAuthenticated = !!user;
if (user) {
authStore.uid = user.uid;
authStore.isAuthenticated = true
try {
await commonStore.getHotelRules()
guestStore.getUserData(user.uid)
} catch (e) {
Notify.create({
type: 'negative',
icon: 'mdi-alert',
message: 'An error happened while fetching misc data, please let us know about this error.',
actions: [
{
label: 'Ok',
color: 'white',
handler: () => {
/* ... */
},
},
],
});
}
} else {
authStore.isAuthenticated = false
guestStore.listeners.userData()
localStorage.clear();
sessionStorage.clear();
}
});
})
上传任务是在所有这些身份验证过程之后执行的...正如我所说,这种情况是随机发生的,并非所有用户都会遇到此错误。
其实我一直无法复制,即使有问题的用户我可以登录他们的帐户也无法复制。
更新,经过更深入的挖掘,我刚刚发现问题与应用程序流程中执行的 emailUpdate 操作有关。
基本上,当我的用户第一次登录时,应用程序会询问他们的电子邮件(用户是使用虚拟电子邮件和密码随机生成的),因此由于此操作应该在用户最近登录时完成,我在他们登录时要求提供电子邮件,并继续更新电子邮件,但显然,如果用户更改电子邮件,JWT 令牌(据我了解)将会更改,甚至某些操作可以在不进行更改的情况下完成重新验证,有些不会,所以在电子邮件更新操作之后我的下一步是使用新凭据重新验证用户。
为了完成此任务,我不仅要求用户提供电子邮件,还要求提供新密码,并在用户提供密码时进行整个更新和重新身份验证。
到目前为止,这似乎缓解了这个问题。
如果有人遇到同样的问题,请确保在更新用户的电子邮件或密码后重新验证用户的身份。