页面保护
NuxtAuth 提供了不同的页面保护方法
- 全局中间件:保护所有页面,可手动排除例外
- 本地中间件:保护特定页面
- 自定义中间件:创建您自己的中间件
全局中间件
要在您的应用上启用全局中间件,您可以在 nuxt.config.ts 中配置中间件。
export default defineNuxtConfig({
modules: ['@sidebase/nuxt-auth'],
auth: {
globalAppMiddleware: true
}
})
如果您想进一步自定义全局中间件,您可以将配置对象传递给 globalAppMiddleware。请参阅此处的 API 参考。
禁用全局中间件
如果全局中间件被禁用,您可以手动将中间件添加到各个页面。这仅在全局中间件被禁用时可用,否则您会收到类似于 Error: Unknown route middleware: 'auth' 的错误。这是因为 auth 中间件是全局添加的,不能用作本地的、页面特定的中间件。
<script lang="ts" setup>
definePageMeta({
middleware: 'sidebase-auth'
})
</script>
<template>
Only I am protected!
</template>
本地中间件
要在单个页面上本地启用或禁用中间件,您可以使用 definePageMeta
宏来为单个页面设置身份验证元数据。
<script setup lang="ts">
definePageMeta({
auth: false
})
</script>
<template>
I am not protected anymore!
</template>
中间件选项
auth
可以是布尔值或包含更多中间件配置的对象。
<script setup lang="ts">
definePageMeta({
auth: {
unauthenticatedOnly: false,
navigateUnauthenticatedTo: '/auth/signin'
}
})
</script>
<template>
I am protected with a custom redirect!
</template>
unauthenticatedOnly
是否仅允许未经身份验证的用户访问此页面。已通过身份验证的用户将被重定向到 / 或 navigateAuthenticatedTo 中指定的路由。
如果您想让所有人都能看到该页面,请设置 auth: false
(参见 本地中间件)。
警告
从 0.9.4
版本开始,此选项是必需的,以防止歧义(相关问题)。请确保您设置了它,否则访客模式将默认启用 —— 您的访客将能够看到该页面,但您已通过身份验证的用户将被重定向走。
navigateAuthenticatedTo
如果 unauthenticatedOnly
设置为 true
,则将已通过身份验证的用户重定向到哪里。
navigateUnauthenticatedTo
如果此页面受到保护,则将未经身份验证的用户重定向到哪里。
访客模式
您可以使用 NuxtAuth 设置仅在用户未登录时才可访问的页面。这有时被称为“访客模式”。此类页面的行为如下:
- 已登录用户访问页面 -> 重定向到另一个(可能是受保护的)页面,
- 已登出用户访问页面 -> 他们被允许停留并查看
这种行为对于您不希望已登录用户访问的登录页面非常有用:为什么他们应该再次经历登录流程?
<script setup lang="ts">
definePageMeta({
auth: {
unauthenticatedOnly: true,
navigateAuthenticatedTo: '/profile'
}
})
</script>
<template>
I can only be viewed as a guest!
</template>
自定义中间件
您可以创建自己的应用侧中间件,以便实现自定义的、更高级的身份验证逻辑。
警告
创建自定义中间件是一个高级的、实验性的选项,如果您不熟悉高级的 Nuxt 3 概念,可能会导致意外或不期望的行为。
要实现您的自定义中间件
- 创建一个应用侧中间件,它可以全局应用或被命名(更多信息请参阅 Nuxt 文档)
- 基于
useAuth
向其添加逻辑
在添加逻辑时,您需要注意在调用其他 async
composable 函数时。这可能会导致 Nuxt 中的 context
问题,请参阅此处的解释。为了避免这些问题,您需要:
- 在等待其他 composables 时,使用未文档化的
callWithNuxt
实用程序 - 尽可能返回一个 async 函数而不是等待它,以避免
callWithNuxt
// file: ~/middleware/authentication.global.ts
export default defineNuxtRouteMiddleware((to) => {
const { status, signIn } = useAuth()
// Return immediately if user is already authenticated
if (status.value === 'authenticated') {
return
}
/**
* We cannot directly call and/or return `signIn` here as `signIn` uses async composables under the hood, leading to "nuxt instance undefined errors", see https://github.com/nuxt/framework/issues/5740#issuecomment-1229197529
*
* So to avoid calling it, we return it immediately.
*/
return signIn(undefined, { callbackUrl: to.path }) as ReturnType<typeof navigateTo>
})
// file: ~/middleware/authentication.global.ts
import { useNuxtApp } from '#imports'
import { callWithNuxt } from '#app/nuxt'
export default defineNuxtRouteMiddleware((to) => {
// It's important to do this as early as possible
const nuxtApp = useNuxtApp()
const { status, signIn } = useAuth()
// Return immediately if user is already authenticated
if (status.value === 'authenticated') {
return
}
/**
* We cannot directly call and/or return `signIn` here as `signIn` uses async composables under the hood, leading to "nuxt instance undefined errors", see https://github.com/nuxt/framework/issues/5740#issuecomment-1229197529
*
* So to avoid calling it, we call it via `callWithNuxt`.
*/
await callWithNuxt(nuxtApp, signIn, [undefined, { callbackUrl: to.path }])
})