繁体   English   中英

在 Pinia 商店中存储 Firebase accessToken - Vue3

[英]Storing Firebase accessToken in Pinia store - Vue3

我是 Vue 的新手,这是我第一次使用 Pinia。 我正在按照本指南设置 Firebase、Pinia 和 Axios。我正在构建的应用程序使用 FirebaseUI 通过 email 链接让用户登录 - 这一切都发生在下面的 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 商店用户 object,AuthResult 从signInSuccessWithAuthResult function返回 object。调试器时,我可以看到存储的 object 如下所示:

{
    additionalUserInfo: {...}
    operationType: "signIn"
    user: {
        accessToken: "eyJhbGciOiJSUzI1N..."
        auth: {...}
        displayName: null
        ...
    }
}

即正在存储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时,它已经消失了。 用户 object 的大部分(如果不是全部)其他属性仍然存在,但访问令牌不存在,因此我很确定我正在正确使用商店:

{
    additionalUserInfo: {...}
    credential: null
    operationType: "signIn"
    user: {
        // accessToken is gone
        apiKey: "..."
        appName: "[DEFAULT]"
        email: "..."
        emailVerified: true
        ....
    }
}

谁能解释我哪里出了问题,以及为什么要从商店中删除accessToken 在我看来,我好像正确地使用了 Pinia 商店,而且我很确定拦截器也是正确的。 但是,我可能会以错误的方式存储访问令牌。 对于如何使用 Vue 正确设置 Firebase 身份验证的任何帮助/建议,我将不胜感激。

编辑为在拦截器内部调试时包含用户存储的值。

看起来 accessToken 可能在 userStore.user.user.accessToken 中?

我刚刚结束了与您所处的同一场战斗……IMO 有很多方法可以配置此设置……这类似于您可能在一个地方使用回调,而在另一个地方使用异步等待的原因,这取决于您的项目结构体。

这是一个简单的示例,可能会帮助您阐明它。

首先创建一个 firebase 文件来保存配置,将其放在您的组织习惯要求您放置的位置。 请记住,以便我们稍后使用它。

import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";

const firebaseConfig = {
  apiKey: "",
  authDomain: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
  measurementId: "",
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

//initialize firebase auth
export const auth = getAuth(app);

第二 - userStore

用户商店负责跑腿工作。 当我们想从我们的 ui 与 userauth 交互时,我们将使用这些操作。

import {
  createUserWithEmailAndPassword,
  onAuthStateChanged,
  signInWithEmailAndPassword,
  signOut,
} from "firebase/auth";

import { auth } from "../firebase"; // the file we made above

import router from "../router";

export const useUserStore = defineStore("userStore", {
  state: () => ({
    userData: null,
    loadingUser: false,
    loadingSession: false,
  }),
  actions: {
    async registerUser(email, password) {
      this.loadingUser = true;
      try {
        const { user } = await createUserWithEmailAndPassword(
          auth,
          email,
          password
        );
        this.userData = { email: user.email, uid: user.uid };
        router.push("/");
      } catch (error) {
        console.log(error);
      } finally {
        this.loadingUser = false;
      }
    },
    async loginUser(email, password) {
      this.loadingUser = true;
      try {
        const { user } = await signInWithEmailAndPassword(
          auth,
          email,
          password
        );
        this.userData = { email: user.email, uid: user.uid };
        router.push("/");
      } catch (error) {
        console.log(error);
      } finally {
        this.loadingUser = false;
      }
    },
    async logOutUser() {
      try {
        await signOut(auth);
        this.userData = null;
        router.push("/login");
      } catch (error) {
        console.log(error);
      }
    },
    currentUser() {
      return new Promise((resolve, reject) => {
        const unsuscribe = onAuthStateChanged(
          auth,
          (user) => {
            if (user) {
              this.userData = { email: user.email, password: user.password };
            } else {
              this.userData = null;
            }
            resolve(user);
          },
          (e) => reject(e)
        );
        unsuscribe();
      });
    },
  },
});

*** step3 在 vue 中设置登录/注册组件。 ***

  <div>
    <form @submit.prevent="login">
      <label>
        Email:
        <input type="email" v-model="email" required />
      </label>
      <br />
      <label>
        Password:
        <input type="password" v-model="password" required />
      </label>
      <br />
      <button type="submit">Login</button>
    </form>
  </div>
</template>

<script>
import { useUserStore } from "../stores/user";
export default {
  data() {
    return {
      email: "",
      password: "",
    };
  },
  methods: {
    async login() {
      try {
        await this.userStore.loginUser(this.email, this.password);  // 
      } catch (error) {
        console.error(error);
      }
    },
  },

// because of below setup you can access this.userStore() singleton 

  setup() {  
    const userStore = useUserStore();
    return {
      userStore,
    };
  },
};
</script>

注册将是simailar

  <div>
    <form @submit.prevent="register">
      <label>
        Email:

        <input type="email" v-model="email" required />
      </label>
      <br />
      <label>
        Password:
        <input type="password" v-model="password" required />
      </label>
      <br />
      <button type="submit">Register</button>
    </form>
  </div>
</template>
<script>
import { useUserStore } from "../stores/user";
export default {
  data() {
    return {
      email: "",
      password: "",
    };
  },
  methods: {
    async register() {
      try {
        await this.userStore.registerUser(this.email, this.password);
      } catch (error) {
        console.error(error);
      }
    },
  },
  setup() {
    const userStore = useUserStore();
    return {
      userStore,
    };
  },
};
</script>

现在只要你想访问用户,它就在 userStore.userData 中

如果您还没有 userStore,只需使用 useUserStore() 方法并以与登录/注册视图中的设置相同的方式访问它

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM