跳至内容

Firebase 身份验证

Firebase 身份验证 使得在您的应用程序中添加不同类型的身份验证以及与 Firestore 和数据库的安全规则集成变得非常容易。大多数 API 可以像您通常使用 Firebase 一样使用,VueFire 公开了几个可组合函数以更好地与 Vue 集成。

安装

首先将 VueFireAuth 模块添加到 VueFire 插件中

ts
import { VueFire, VueFireAuth } from 'vuefire'
app.use(VueFire, {
  firebaseApp: createFirebaseApp(),
  modules: [
    // ... other modules
    VueFireAuth(),
  ],
})

这将自动初始化并注入 Auth 模块 以及本页中描述的其他功能。

或者,您也可以使用 VueFireAuthWithDependencies(),如果您想手动指定其依赖项

ts
import { VueFire, VueFireAuthWithDependencies } from 'vuefire'
import {
  browserLocalPersistence,
  debugErrorMap,
  indexedDBLocalPersistence,
  prodErrorMap,
} from 'firebase/auth'

app.use(VueFire, {
  firebaseApp: createFirebaseApp(),
  modules: [
    // ... other modules
    VueFireAuthWithDependencies({
      dependencies: {
        errorMap:
          process.env.NODE_ENV !== 'production'
            ? debugErrorMap
            : prodErrorMap,
        persistence: [
          indexedDBLocalPersistence,
          browserLocalPersistence,
        ]
      }
    }),
  ],
})

这样做将允许您在浏览器以外的环境中使用 VueFire。有关更多信息,请参阅 Firebase 文档

Auth 实例

您可以使用 useFirebaseAuth() 可组合函数在任何组件中访问当前 Auth 实例

vue
<script setup>
const auth = useFirebaseAuth()
</script>

如果您想使用 Firebase Auth API 登录用户、创建用户等,则需要这样做。

vue
<script setup>
import {
  getRedirectResult,
  signInWithRedirect,
  signOut,
} from 'firebase/auth'
import { useCurrentUser, useFirebaseAuth } from 'vuefire'

const auth = useFirebaseAuth() // only exists on client side

// display errors if any
const error = ref(null)
function signinRedirect() {
  signInWithRedirect(auth, someAuthProvider).catch((reason) => {
    console.error('Failed signinRedirect', reason)
    error.value = reason
  })
}

// only on client side
onMounted(() => {
  getRedirectResult(auth).catch((reason) => {
    console.error('Failed redirect result', reason)
    error.value = reason
  })
})
</script>

<template>
  <main>
    <ErrorBox v-if="error" :error="error" />
    <button @click="signinRedirect()">SignIn with Google</button>
  </main>
</template>

提示

useFirebaseAuth() 在服务器端为 null,因此如果您使用 TypeScript,您可能需要添加一个 ! 来断言它不为 null。

ts
const auth = useFirebaseAuth()!

提供者

有多种方法可以将身份验证提供者添加到您的应用程序中,例如从我们初始化 Firebase 的文件中导出 new GoogleAuthProvider() 实例。另一种方法是在您需要它的组件中直接创建它。确保将其添加到常规 <script> 中,因为每个 <script setup> 都作用域到组件实例

vue
<script>
import { GoogleAuthProvider } from 'firebase/auth'
export const googleAuthProvider = new GoogleAuthProvider()
</script>

<script setup>
import {
  signInWithPopup,
  signOut,
} from 'firebase/auth'
import { useCurrentUser, useFirebaseAuth } from 'vuefire'

//...

function signinPopup() {
  error.value = null
  signInWithPopup(auth, googleAuthProvider).catch((reason) => {
    console.error('Failed sign', reason)
    error.value = reason
  })
}
</script>

当前用户

您可以使用 useCurrentUser() 可组合函数将当前用户作为响应式变量获取

vue
<script setup>
import { useCurrentUser } from 'vuefire'

const user = useCurrentUser()
</script>

<template>
  <p v-if="user">Hello {{ user.providerData.displayName }}</p>
</template>

等待用户加载

useCurrentUser() 可组合函数将为您提供一个 undefined 值,直到用户加载完毕。然后它将变为 null 或用户对象本身。如果您需要以声明式方式等待用户加载,您可以使用 useIsCurrentUserLoaded() 可组合函数。在内部,它只是一个计算属性,当用户不为 undefined 时返回 true

还有一个 getCurrentUser() 函数,它返回当前用户的承诺。如果您想在执行任何操作之前等待用户加载,这很有用。例如,您可以在导航守卫中等待它

ts
router.beforeEach(async (to) => {
  // routes with `meta: { requiresAuth: true }` will check for
  // the users, others won't
  if (to.meta.requiresAuth) {
    const currentUser = await getCurrentUser()
    // if the user is not logged in, redirect to the login page
    if (!currentUser) {
      return {
        path: '/login',
        query: {
          // we keep the current path in the query so we can
          // redirect to it after login with
          // `router.push(route.query.redirect || '/')`
          redirect: to.fullPath,
        },
      }
    }
  }
})

提示

如果您在导航守卫中使用 getCurrentUser(),请确保在调用 app.use(router) 之前添加它,因为这将触发初始导航。

用户加载后,getCurrentUser() 将立即解析当前用户。

有时,Firebase SDK 可能会使用隐藏的 cookie 或本地存储自动登录用户。在这种情况下,您可以自动将用户重定向到他们在自动登录之前尝试访问的页面。您甚至可以在他们注销时将他们重定向到登录页面

ts
// App.vue
const user = useCurrentUser()
const router = useRouter()
const route = useRoute()

watch(user, async (currentUser, previousUser) => {
  // redirect to login if they logout and the current
  // route is only for authenticated users
  if (
    !currentUser &&
    previousUser &&
    isCurrentRouteAuthenticated(route)
  ) {
    return router.push({ name: 'login' })
  }
  // redirect the user if they are logged in but were
  // rejected because the user wasn't ready yet, logged in
  // then got back to this page
  if (currentUser && typeof route.query.redirect === 'string') {
    return router.push(route.query.redirect)
  }
})