Firebase 身份验证
Firebase 身份验证 使得在您的应用程序中添加不同类型的身份验证以及与 Firestore 和数据库的安全规则集成变得非常容易。大多数 API 可以像您通常使用 Firebase 一样使用,VueFire 公开了几个可组合函数以更好地与 Vue 集成。
安装
首先将 VueFireAuth
模块添加到 VueFire
插件中
import { VueFire, VueFireAuth } from 'vuefire'
app.use(VueFire, {
firebaseApp: createFirebaseApp(),
modules: [
// ... other modules
VueFireAuth(),
],
})
这将自动初始化并注入 Auth 模块 以及本页中描述的其他功能。
或者,您也可以使用 VueFireAuthWithDependencies()
,如果您想手动指定其依赖项
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 实例
<script setup>
const auth = useFirebaseAuth()
</script>
如果您想使用 Firebase Auth API 登录用户、创建用户等,则需要这样做。
<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。
const auth = useFirebaseAuth()!
提供者
有多种方法可以将身份验证提供者添加到您的应用程序中,例如从我们初始化 Firebase 的文件中导出 new GoogleAuthProvider()
实例。另一种方法是在您需要它的组件中直接创建它。确保将其添加到常规 <script>
中,因为每个 <script setup>
都作用域到组件实例
<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()
可组合函数将当前用户作为响应式变量获取
<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()
函数,它返回当前用户的承诺。如果您想在执行任何操作之前等待用户加载,这很有用。例如,您可以在导航守卫中等待它
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 或本地存储自动登录用户。在这种情况下,您可以自动将用户重定向到他们在自动登录之前尝试访问的页面。您甚至可以在他们注销时将他们重定向到登录页面
// 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)
}
})