Nuxt.js中如何限制特定路由仅对持有有效JWT令牌的客户端开放及验证逻辑实现位置问询
刚好在Nuxt里做过不少JWT路由保护的需求,我分Nuxt 2和Nuxt 3两种主流版本来给你讲具体实现,毕竟两者的架构差异挺大的:
在Nuxt 2中实现JWT校验保护路由
Nuxt 2里核心是用**中间件(Middleware)**来拦截路由请求,同时在API路由里单独做令牌校验:
1. 创建路由保护中间件
在项目根目录的 middleware/ 文件夹下新建 auth.js,写入校验逻辑:
import jwt from 'jsonwebtoken' export default function ({ req, res, redirect }) { // 优先从请求头拿令牌(服务端渲染场景),其次从cookie拿(客户端渲染场景) const token = req.headers.authorization?.split(' ')[1] || req.cookies.token // 无令牌直接跳转到登录页 if (!token) { return redirect('/login') } try { // 替换成你自己的JWT密钥,建议存在环境变量里 jwt.verify(token, process.env.JWT_SECRET) } catch (err) { // 令牌过期或无效,清空cookie并跳转登录 res.clearCookie('token') return redirect('/login') } }
2. 应用中间件到受保护路由
- 单个页面保护:在需要限制的页面组件(比如
pages/dashboard.vue)里添加配置:
<script> export default { middleware: 'auth' // 指定使用刚才创建的auth中间件 } </script>
- 全局路由保护:如果大部分路由都需要校验,可在
nuxt.config.js里全局注册:
export default { router: { middleware: ['auth'] } }
3. API路由的JWT校验
对于后端API(server/api/ 下的路由),直接在路由处理函数开头做校验:
import jwt from 'jsonwebtoken' export default function (req, res) { const token = req.headers.authorization?.split(' ')[1] if (!token) { res.status(401).json({ message: '未提供有效令牌' }) return } try { const decodedUser = jwt.verify(token, process.env.JWT_SECRET) // 可以把解码后的用户信息挂载到req上,供后续逻辑使用 req.user = decodedUser // 处理正常的API请求逻辑 res.status(200).json({ data: '仅授权用户可见的数据' }) } catch (err) { res.status(401).json({ message: '令牌无效或已过期' }) } }
在Nuxt 3中实现JWT校验保护路由
Nuxt 3基于Nitro引擎,支持页面中间件和服务端中间件两种方式,API路由的校验逻辑也更简洁:
1. 页面级路由保护
在 middleware/ 文件夹下新建 auth.ts(或js):
import { jwtVerify } from 'jose' // 推荐用jose库,比jsonwebtoken更适配现代Node环境 export default defineNuxtRouteMiddleware(async (to, from) => { // 从cookie或请求头获取令牌 const token = useCookie('token').value || useRequestHeaders(['authorization']).authorization?.split(' ')[1] if (!token) { return navigateTo('/login') } try { // 验证令牌有效性 await jwtVerify(token, new TextEncoder().encode(process.env.JWT_SECRET)) } catch (err) { // 令牌无效,清空cookie并跳转登录 useCookie('token').value = null return navigateTo('/login') } })
然后在需要保护的页面组件里通过 definePageMeta 绑定中间件:
<script setup> definePageMeta({ middleware: 'auth' }) </script>
2. API路由的JWT校验
在 server/api/ 下的路由文件(比如 protected.get.ts)里,直接在处理函数开头做校验:
import { jwtVerify } from 'jose' export default defineEventHandler(async (event) => { const token = getRequestHeader(event, 'authorization')?.split(' ')[1] if (!token) { throw createError({ statusCode: 401, message: '未授权访问' }) } try { const { payload } = await jwtVerify(token, new TextEncoder().encode(process.env.JWT_SECRET)) // 将用户信息挂载到event.context,供后续逻辑使用 event.context.user = payload return { data: '仅授权用户可访问的API数据' } } catch (err) { throw createError({ statusCode: 401, message: '令牌无效或已过期' }) } })
关键提醒
注意:前端中间件只是用来优化用户跳转体验,绝对不能替代后端API的JWT校验! 前端逻辑可以被篡改绕过,只有后端的校验才能真正保证接口的安全性。
内容的提问来源于stack exchange,提问作者user16799703
相关产品推荐
相关产品推荐

