vue.js 如何在firebase-auth中第一次加载时获取currentUser而无需请求

bfrts1fy  于 2023-03-03  发布在  Vue.js
关注(0)|答案(3)|浏览(158)

我使用的是firebase身份验证,我的导航栏取决于用户是否登录。当我加载网站时,如果用户之前没有注销,他应该仍然保持登录状态。但是,Firebase onAuthStateChanged侦听器在100- 300 ms后返回用户,所以我的导航栏无法确定用户是否登录。因此,导航栏显示登录和注册按钮300 ms,然后firebase返回用户,导航栏显示 Jmeter 板和注销按钮。
我正在使用vue,我尝试过在本地存储器上保存UID和用户名,但我担心安全性。如果有人手动更改了本地存储器数据会怎么样?此外,用户可能会注销,但仍然登录在我手动设置的localStorage.setItem('user',....)
Navbar.vue

<div v-if="user.uid" class="flex row space-b">
   // userpic, photo, logout button
</div>
<div v-else>
   // login and signup button 
</div>

武埃克斯

state: {
user: {
  uid: null,
  photoURL: null,
  username: null,
},
},

我试着不挂载Vue示例,直到onAuthStateChanged侦听器返回一些东西,但这不是一个好的解决方案,因此我渲染网站近300毫秒晚。

6bc51xsx

6bc51xsx1#

无论如何,我把它保存在cookie中。当网站加载时,如果cookie存在,我会呈现导航栏,就像用户登录一样,然后在Firebase侦听器返回后仔细检查

xnifntxz

xnifntxz2#

这是因为beforeEach在firebase完全完成初始化之前执行。
您可以使用onAuthStateChanged观察器来确保仅在firebase完全初始化之后才初始化vue应用。
修复它的一种方法是使用onAuthStateChanged将vue初始化代码 Package 在main.js(new Vue(...))中,如下所示:

let app;

const auth = getAuth();
onAuthStateChanged(auth, (user) => {
  console.log("user", user);
  if (!app) {
    new Vue({
      router,
      vuetify: new Vuetify(options.Vuetify),
      render: (h) => h(App),
    }).$mount("#app");
  }
});

对于版本7 firebase,您可以检查此存储库文件https://github.com/ErikCH/FirebaseTokenFrontend/blob/master/src/main.js

vlju58qv

vlju58qv3#

@Abdullah Alhariri给出的answer可以工作。但是,它会阻止VUE加载,除非firebase auth已经初始化。这可能会导致用户长时间黑屏。这里有一个解决方案(灵感来自LearnVue的this video
main.js文件不应包含对firebase的任何导入或引用。
src/helper文件夹中添加firebase.js,在该文件中,我们正在设置firebase项目和auth,重要部分是getCurrentUser()函数,该函数将在router.js中使用

// Firebase App (the core Firebase SDK) is always required and must be listed first
import { initializeApp } from 'firebase/app';
// Add the Firebase products that you want to use
import { getAuth, onAuthStateChanged } from 'firebase/auth';

// Firebase config we got from firebase console.
const firebaseConfig = {
  // Your config
};

// Initlise Firebase
const firebaseApp = initializeApp(firebaseConfig);
// Authentication
export const fbAuth = getAuth(firebaseApp);

export async function getCurrentUser() {
  return new Promise((resolve, reject) => {
    // If the user is already found, then the firebase is initialized.
    //  In this case, simply return the user.
    if (fbAuth.currentUser) {
      resolve(fbAuth.currentUser)
      return
    }
    // The user is not found, hence listen to the change
    const removeListener = onAuthStateChanged(
      fbAuth,
      (user) => {
        removeListener(); // After initialized, remove the listner for better JS memory management
        resolve(user) // return user. If the user is not logged in, this will be null.
      },
      reject
    )
  })
}

router.js中,对于每条路由,使用meta定义哪些路由需要认证,然后在router.beforeEach()(即路由器保护)中使用getCurrentUser()函数。
注意:使用async作为router.beforeEach(),这样可以确保只有在初始化firebase auth之后才能导航路由。

import { createRouter, createWebHistory } from 'vue-router'
// Firebase
import { getCurrentUser } from "@/helper/firebase"

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: "/",
      name: "WebsiteHome",
      meta: { title: "Jamku Portal", isAuth: false },
    },
    
    {
      path: "/admin",
      name: "Admin",
      meta: { title: "Admin", isAuth: true },
    },
    {
      path: "/pricing",
      name: "Pricing",
      meta: { title: "Jamku Portal Pricing", isAuth: false },      
    },
  ],
  }
});

router.beforeEach(async (to, from, next) => {

  // Add page title for browser
  document.title = to.meta.title || "Jamku Portal";

  // Initalize firebase if the route requires auth
  if (to.meta?.isAuth == true) {
    await getCurrentUser()
  }

  // Always call next() other wise Vue will never proceed further
  next();
});

相关问题