在Nuxt 3中使用defineNuxtRouteMiddleware实现导航保护
**由 Paul Akinyemi✏️ 撰写**
导航保护功能可让您控制谁可以访问应用程序的特定部分,确保只有授权用户才能访问特定页面。这可增强安全性并改善用户体验,让您的应用程序安全高效。
在本文中,我们将介绍导航保护是什么、它们与中间件的关系以及如何在 Nuxt 3 中编写导航保护。术语“中间件”将用于指代路由中间件,它在 Nuxt 应用程序的 Vue 部分运行,与 Nuxt 的服务器中间件不同。
什么是导航守卫?
导航守卫是一些在页面请求之后但呈现之前运行的代码,用于确保只有授权用户才能访问某些功能。导航守卫用于实现以下功能:
使用 Nuxt 中间件创建导航守卫
为了创建导航保护,我们将利用 Nuxt 中称为中间件的概念。Nuxt 中的中间件是在页面呈现之前运行的特殊函数,使其成为实现导航保护的理想选择。
Nuxt 中有三种类型的中间件:匿名、命名和全局。当你想使用匿名和命名中间件时,你必须在要保护的页面上明确定义它。相反,全局中间件适用于所有页面。
中间件语法
这是所有中间件采用的一般形式:
(from, to) => { if (someCondition) { return navigateTo("/route") } if (otherCondition) { return abortNavigation() //or return abortNavigation(error) } // return nothing to allow the request to proceed normally }
请注意,中间件也可以是“异步”函数,如果需要,它允许您“等待”异步请求。
每个中间件都是一个接受两个路由对象作为参数的函数:
以下是“route”对象的几个属性:
您可以在此处找到完整的属性列表。
函数“navigateTo”和“abortNavigation”允许您实现导航保护功能。“navigateTo”允许您将用户重定向到另一条路径,而“abortNavigation”允许您完全终止导航。这两个函数都是全局可用的,因此不需要导入。
现在我们知道如何编写中间件函数,让我们看看如何为特定页面或全局注册一个中间件函数。
编写匿名中间件
匿名中间件,也称为内联中间件,是在页面内部定义的中间件,因此仅在该页面上运行。
要编写匿名中间件,您只需在编译器宏的“中间件”数组内编写中间件函数。
以下是一个例子:
// pages/staff.vue
注意:你可以在一个页面上定义多个匿名中间件,它们将按照它们在“中间件”数组中出现的顺序执行。
就这样!接下来,我们将研究如何编写命名中间件。
使用 defineNuxtRouteMiddleware 编写命名中间件
命名中间件是在 `middleware` 目录中的独立文件中定义的中间件,可以在多个页面上运行。中间件的名称是其包含文件的短横线命名名称,因此位于文件 `middleware/isAdmin.js` 中的中间件将获得名称 `is-admin`。
要创建命名中间件,我们还需要一件事:一个名为“defineNuxtRouteMiddleware”的辅助函数。此辅助函数将中间件函数作为其唯一参数。
要创建一个命名中间件,首先必须在 `middleware` 目录中创建一个文件,然后编写中间件,将其传递给 `defineNuxtRouteMiddleware`,并导出返回值。以下是示例:
// middleware/isAdmin.js export default defineNuxtRouteMiddleware((to, from) => { // isUserAdmin() is a dummy function const isAdmin = isUserAdmin() if (!isAdmin) { // Redirect the user to the homepage return navigateTo('/') } // Else, continue with navigation })
现在您已经创建了 `is-admin` 中间件,您可以通过将其名称放入 `definePageMeta` 宏的 `middleware` 数组中来在任何页面上使用它。以下是一个例子:
// pages/staff.vue
就是这样!
编写全局中间件
编写全局中间件的方式与编写命名中间件的方式相同,但有一点不同:中间件文件的名称必须以 `.global` 为后缀。因此,该文件将被命名为 `middleware/isAdmin.global.js`,而不是 `middleware/isAdmin.js`,然后它将在每个路由上运行,而无需在 `definePageMeta` 中指定。
请注意,无法为全局中间件定义异常 — 它们始终在每个路由上运行。如果您希望全局中间件跳过某个路由,则必须在中间件内部编写检查。
中间件排序
在任何给定的路由上,中间件按以下顺序执行:
全局中间件根据文件名按字母顺序执行,但如果您需要按特定顺序运行中间件,则可以在其前面加上数字,例如:“middleware/01.isAdmin.global.js”。
使用导航守卫时的最佳实践
以下是编写导航保护时需要牢记的一些准则。
导航卫士应该精简
您应该编写导航保护来做尽可能少的工作;每个函数运行的时间越长,用户等待页面呈现的时间就越长。
如果可能的话,您应该避免发出网络请求,如果不能,您应该一次获取和缓存尽可能多的数据。
导航守卫应该是纯函数
尽管 Nuxt 保证了中间件的执行顺序,但每个中间件函数都应该没有副作用,并且无论在中间件链中的哪个位置执行都应该完全相同地运行。
小心无限重定向
如果不小心,通过编写如下中间件很容易创建无限重定向:
export default defineNuxtRouteMiddleware((to, from) => { const { isAuthenticated } = dummyAuthFunction(); if (!isAuthenticated) { return navigateTo('/login') } else { return navigateTo('/') } })
这个中间件乍一看没什么问题,但它有一个问题:无论条件值是什么,你总是在重定向。如果这个中间件在你访问要重定向到的页面时也会执行,这将创建一个无限循环。以下是修改代码以修复此问题的方法:
export default defineNuxtRouteMiddleware((to, from) => { const { isAuthenticated } = dummyAuthFunction(); if (!isAuthenticated) { return navigateTo('/login') } })
这里的关键是,当您不需要转移用户时,不要重定向到特定路线,而是返回任何内容(允许导航继续)。
结论
导航保护是 Nuxt 3 中的一项强大功能,可帮助您控制对应用程序路由的访问。通过利用中间件(无论是匿名、命名还是全局),您可以高效地实施这些保护以增强安全性和用户体验。保持中间件精简和纯粹,您将确保整个应用程序的导航顺畅而有效。
几分钟内即可设置 LogRocket 的现代错误跟踪:
新版本:
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
脚本标记:
Add to your HTML:
3.(可选)安装插件以便与您的堆栈进行更深入的集成:
现在就开始。