【问题标题】:Firebase auth coming as null in nuxtjs middleware on page reloadFirebase 身份验证在页面重新加载时在 nuxtjs 中间件中为空
【发布时间】:2023-03-30 20:40:01
【问题描述】:

nuxtjs 新手。我正在为 firebase 使用 Nuxt firebase(https://firebase.nuxtjs.org/) 库。成功登录后,我将用户重定向到“/member/desk”路线。但是,一旦重定向到该特定页面,如果我刷新页面,我就会重定向到“/auth/signin”页面。这是因为在“middleware/auth.js”文件中我没有得到app.$fire.auth.currentUser 值作为null

我用谷歌搜索了这个,但没有任何可靠的信息可以解决我的问题。需要一些帮助。

这是我的文件..

  • nuxt.config.js
[
    '@nuxtjs/firebase',
    {
        config: {
            apiKey: "",
            authDomain: "",
            projectId: "",
            storageBucket: "",
            messagingSenderId: "",
            appId: "",
            measurementId: ""
        },
        services: {
            auth: {
            persistence: 'local', // default
            initialize: {
                onAuthStateChangedAction: 'onAuthStateChangedAction',
                subscribeManually: false
            },
            ssr: false
            }
        }
    }
]
  • 存储/index.js
const actions = {
    async onAuthStateChangedAction(state, { authUser, claims }) {
        if (!authUser) {
            // remove state
            state.commit('SET_USER', null)

            //redirect from here
            this.$router.push({
                path: '/auth/signin',
            })
        } else {
            // console.log('authUser', authUser);
            const { uid, email } = authUser
            state.commit('SET_USER', {
                uid,
                email,
            })
        }
    },
}

const mutations = {
    SET_USER(state, user) {
        state.user = user
    },
}

const state = () => ({
    user: null,
})

const getters = {
    getUser(state) {
        return state.user
    },
}

export default {
    state,
    actions,
    mutations,
    getters,
}

  • 中间件/auth.js
export default function ({ store, app, route, redirect }) {
    if (route.path === '/') {
        //leave them on the sign in page
    } else if (route.path !== '/auth/signin') {
        //we are on a protected route
        console.log('app.$fire.auth', app.$fire.auth.currentUser);
        if (!app.$fire.auth.currentUser) {
            //take them to sign in page
            return redirect('/auth/signin')
            // return redirect('/auth/signout')
        }
    } else if (route.path === '/auth/signin') {
        if (!app.$fire.auth.currentUser) {
            //leave them on the sign in page
        } else {
            return redirect('/')
        }
    }
}

  • pages/index.js
<template>
  <v-row justify="center" align="center">
    <v-col cols="12" sm="8" md="4">
      <v-form ref="form" v-model="valid" lazy-validation>
        <v-text-field
          v-model="email"
          :rules="emailRules"
          type="email"
          label="E-mail"
          autocomplete="username"
          required
        ></v-text-field>

        <v-text-field
          v-model="password"
          :rules="passwordRules"
          type="password"
          label="Password"
          autocomplete="current-password"
          required
        ></v-text-field>

        <v-btn :disabled="!valid" color="success" class="mr-4" @click="login">
          Login
        </v-btn>
      </v-form>
    </v-col>
  </v-row>
</template>

<script>
export default {
  layout: "plain",
  data: () => ({
    valid: true,
    name: "",
    nameRules: [
      (v) => !!v || "Name is required",
      (v) => (v && v.length <= 10) || "Name must be less than 10 characters",
    ],
    password: "",
    passwordRules: [
      (v) => !!v || "Password is required",
      (v) => (v && v.length >= 6) || "Password must minimums 6 characters",
    ],
    email: "",
    emailRules: [
      (v) => !!v || "E-mail is required",
      (v) => /.+@.+\..+/.test(v) || "E-mail must be valid",
    ],
    select: null,
    items: ["Item 1", "Item 2", "Item 3", "Item 4"],
    checkbox: false,
  }),

  methods: {
    login() {
      let formValidation = this.$refs.form.validate();
      console.log("formValidation", formValidation);

      if (formValidation) {
        this.$fire.auth
          .signInWithEmailAndPassword(this.email, this.password)
          .catch(function (error) {
            // that.snackbarText = error.message;
            // that.snackbar = true;
            console.log("login error", error.message);
            $nuxt.$router.push("/");
          })
          .then((user) => {
            // this.$fire.auth.onAuthStateChanged((user) => {
            //   currentUser = user.uid;
            // });
            //we are signed in
            $nuxt.$router.push("/member/desk");
          });
      }
    },
    reset() {
      this.$refs.form.reset();
    },
    resetValidation() {
      this.$refs.form.resetValidation();
    },
  },
};
</script>

--- 更新 ---

在实施“带有 SSR(https://firebase.nuxtjs.org/tutorials/ssr#step-3---retrieve-the-server-user)的 Firebase 身份验证”后,我设法在一定程度上解决了这个问题。现在,当我刷新(正常重新加载)"/member/desk" route 它现在工作正常(保持在同一页面上)。但是,当我执行 HARD RELOAD 时,它会重定向到“/auth/signin”路由。

我相信这与“服务器工作者”实现有关。在 HARD RELOAD 时,所有缓存的数据都被删除,Service Worker 再次重新启动。

我也可能错了。谁能给我解释一下!!!

【问题讨论】:

    标签: javascript vue.js firebase-authentication nuxt.js


    【解决方案1】:

    正如此处的 firebase 身份验证文档 (https://firebase.google.com/docs/auth/web/manage-users) 所述:

    firebase.auth().currentUser 也可以为 null,因为 auth 对象 尚未完成初始化。如果您使用观察者跟踪 用户的登录状态,无需处理。

    这意味着如果您的中间件被调用得太快 - 当 auth.onStateChanged 尚未完成时 - app.$fire.auth.currentUser 最初将为 null。

    我建议您使用存储在 Vuex 中的用户来更改中间件。

    export default function ({ store, app, route, redirect }) {
        const user = store.state.user;
        if (route.path === '/') {
            //leave them on the sign in page
        } else if (route.path !== '/auth/signin') {
            //we are on a protected route
            if (!user) {
                //take them to sign in page
                return redirect('/auth/signin')
                // return redirect('/auth/signout')
            }
        } else if (route.path === '/auth/signin') {
            if (!user) {
                //leave them on the sign in page
            } else {
                return redirect('/')
            }
        }
    }
    

    【讨论】:

    • 对于user,我也收到了null。附上 chrome 开发工具截图。也许我错过了其他东西。
    • 看起来你的状态在硬重新加载之间没有持久化,你可以使用这个包github.com/robinvdvleuten/vuex-persistedstate或这个github.com/championswimmer/vuex-persist在你的商店配置中做到这一点。之后,您的已连接用户将保持连接状态,您将能够直接通过中间件检查。
    猜你喜欢
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 2020-08-08
    • 2018-08-20
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    相关资源
    最近更新 更多