【发布时间】:2023-01-24 02:27:44
【问题描述】:
我是 Vue 的新手,这是我第一次使用 Pinia。我正在关注 this guide 以设置 Firebase、Pinia 和 Axios。我正在构建的应用程序使用 FirebaseUI 通过电子邮件链接让用户登录 - 这一切都发生在下面的 LoginPage 组件中:
(请忽略所有错误类型的变量/函数——我只是想首先让它工作)
<script setup lang="ts">
import { onMounted } from "vue";
import { EmailAuthProvider } from "firebase/auth";
import { auth } from "firebaseui";
import { auth as firebaseAuth } from "../firebase/config";
import { useUserStore } from "../stores/user"
onMounted(async () => {
const uiConfig: auth.Config = {
signInSuccessUrl: "/",
signInOptions: [
{
provider: EmailAuthProvider.PROVIDER_ID,
signInMethod: EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD,
forceSameDevice: true,
},
],
callbacks: {
signInSuccessWithAuthResult: function (authResult) {
const store = useUserStore();
store.user = authResult;
return true;
},
},
};
const ui = new auth.AuthUI(firebaseAuth);
ui.start("#firebaseui-auth-container", uiConfig);
});
</script>
<template>
<div id="firebaseui-auth-container"></div>
</template>
当用户成功登录时,应用程序更新 Pinia 商店用户对象,使用 AuthResult 从 signInSuccessWithAuthResult 函数返回对象。调试器时,我可以看到正在存储的对象如下所示:
{
additionalUserInfo: {...}
operationType: "signIn"
user: {
accessToken: "eyJhbGciOiJSUzI1N..."
auth: {...}
displayName: null
...
}
}
IE。 accessToken 正在被存储。用户存储如下:
import { defineStore } from 'pinia'
export const useUserStore = defineStore("userStore", {
state: () => ({
user: null as any
}),
getters: {
getUser(state) {
return state.user
}
}
})
在应用程序中,我设置了一个 axios 拦截器,它将 accessToken 附加到应用程序发出的任何 Axios 请求:
axiosInstance.interceptors.request.use((config) => {
const userStore = useUserStore();
if (userStore) {
debugger;
// accessToken is undefined
config.headers.Authorization = 'Bearer ' + userStore.user.user.accessToken;
}
return config;
});
此时尝试从用户存储中检索 accessToken 时,它不见了。用户对象的大多数(如果不是全部)其他属性仍然存在,但访问令牌不存在,因此我很确定我正在正确使用商店:
{
additionalUserInfo: {...}
credential: null
operationType: "signIn"
user: {
// accessToken is gone
apiKey: "..."
appName: "[DEFAULT]"
email: "..."
emailVerified: true
....
}
}
任何人都可以解释我哪里出了问题,以及为什么 accessToken 从商店中删除?在我看来,我好像正确地使用了 Pinia 商店,而且我很确定拦截器也是正确的。但是,我可能会以错误的方式存储访问令牌。对于如何使用 Vue 正确设置 Firebase 身份验证的任何帮助/建议,我将不胜感激。
编辑为在拦截器内部调试时包含用户存储的值。
【问题讨论】:
-
您需要缩小问题范围,它包含不相关的部分。没有解释为什么一个属性会是未定义的,除非你明确地设置它。如果
user为空,user.accessToken将抛出错误。如果等于authResult,并且有accessToken,则定义user.accessToken。store.user = authResult- 这是一个错误。不应直接修改存储状态,只能在操作中修改。然后这可以在开发工具中看到。 “当调试器时,我可以看到”——哪个调试器?我相信这个问题在这一点上是不可重现的。 -
感谢您的评论@EstusFlask - 我只添加了适用于该问题的代码部分。在我的应用程序中,我没有在其他任何地方更新用户 pinia 商店,仅在上面的部分中。我相信我能够直接从组件内部修改状态 - pinia.vuejs.org/core-concepts/state.html#accessing-the-state(无论看起来多么奇怪)。正如你所说,'如果它等于 authResult,并且有 accessToken,user.accessToken 将被定义' - 我完全同意,但是当我访问该对象时,它是未定义的,但用户名、电子邮件等仍然存在。
-
您可以在外部修改状态,但您不应该这样做,这是一种不好的做法,因为它无法跟踪到特定的操作。它尚未在 Pinia 中强制执行,但这种做法是从 Vuex 继承的。请提供一种重现它的方法。目前唯一的解释是没有调试好,不知道具体是怎么调试的。尽可能使用 Pinia devtools
标签: firebase vue.js axios vuejs3 pinia