Firebase 身份验证在页面重新加载时在 nuxtjs 中间件中为空

Posted

技术标签:

【中文标题】Firebase 身份验证在页面重新加载时在 nuxtjs 中间件中为空【英文标题】:Firebase auth coming as null in nuxtjs middleware on page reload 【发布时间】:2021-11-27 11:40:03 【问题描述】:

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
            ,
            s-s-r: 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>

--- 更新 ---

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

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

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

【问题讨论】:

【参考方案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在你的商店配置中做到这一点。之后,您的已连接用户将保持连接状态,您将能够直接通过中间件检查。

以上是关于Firebase 身份验证在页面重新加载时在 nuxtjs 中间件中为空的主要内容,如果未能解决你的问题,请参考以下文章

如何在angular4的firebase电话身份验证中重新发送短信验证?

AngularFireAuth 模拟器登录在页面重新加载时丢失

每当页面重新加载时如何使用tomcat身份验证

Angular:处理重新加载页面和用户身份验证

UITableView 在重新加载页面时在单元格顶部显示额外的分隔线

带有 Firebase 身份验证的 Nuxt s-s-r 身份验证防护