基础篇八 Nuxt4 中间件进阶:请求拦截与权限校验
文章目录一、中间件执行流程二、登录状态检查三、角色权限校验四、页面数据预加载五、访问日志记录六、IP 黑名单服务端七、API 请求拦截八、请求限流九、CORS 配置十、全局错误处理总结个人网站前面我们学过路由守卫用中间件控制页面访问权限。今天深入聊聊中间件的高级用法包括请求拦截、权限校验、数据预加载等实战技巧。一、中间件执行流程理解执行顺序很重要1. 全局中间件按字母排序 2. 页面定义的中间件 3. 布局中间件目录结构middleware/ ├── 01-auth.global.ts # 全局先执行 ├── 02-logging.global.ts # 全局后执行 ├── admin.ts # 页面级 └── guest.ts # 页面级二、登录状态检查最常见的场景// middleware/auth.tsexportdefaultdefineNuxtRouteMiddleware((to,from){constuserStoreuseUserStore()// 未登录跳转登录页if(!userStore.isLoggedIn){// 保存原目标路径登录后跳回returnnavigateTo({path:/login,query:{redirect:to.fullPath}})}})登录页面script setup langts const route useRoute() const userStore useUserStore() const form reactive({ email: , password: }) const login async () { await userStore.login(form.email, form.password) // 登录成功跳回原页面 const redirect route.query.redirect as string navigateTo(redirect || /) } /script三、角色权限校验不同用户有不同权限// middleware/role.tstypeRoleadmin|editor|userexportdefaultdefineNuxtRouteMiddleware((to,from){constuserStoreuseUserStore()// 从路由 meta 获取需要的角色constrequiredRoleto.meta.roleasRoleif(!requiredRole)return// 未登录或权限不足if(!userStore.user||!hasPermission(userStore.user.role,requiredRole)){returnnavigateTo(/403)}})// 权限等级constroleLevel:RecordRole,number{admin:3,editor:2,user:1}consthasPermission(userRole:Role,requiredRole:Role){returnroleLevel[userRole]roleLevel[requiredRole]}页面中使用script setup langts definePageMeta({ middleware: role, meta: { role: admin // 只有管理员能访问 } }) /script四、页面数据预加载中间件可以预加载数据避免页面闪烁// middleware/fetch-user.global.tsexportdefaultdefineNuxtRouteMiddleware(async(to,from){constuserStoreuseUserStore()consttokenuseCookie(token)// 有 token 但没有用户数据尝试获取if(token.value!userStore.user){try{awaituserStore.fetchUser()}catch{// token 失效清除token.valuenull}}})五、访问日志记录记录页面访问// middleware/logging.global.tsexportdefaultdefineNuxtRouteMiddleware((to,from){constuserStoreuseUserStore()// 只在客户端记录if(import.meta.client){constlogData{userId:userStore.user?.id||anonymous,from:from.path,to:to.path,timestamp:newDate().toISOString(),userAgent:navigator.userAgent}// 发送到日志服务不阻塞导航$fetch(/api/logs,{method:POST,body:logData}).catch(console.error)}})六、IP 黑名单服务端// middleware/ip-block.global.tsexportdefaultdefineNuxtRouteMiddleware(async(to,from){// 只在服务端执行if(import.meta.server){consteventuseRequestEvent()constipgetRequestIP(event,{xForwardedFor:true})// 检查 IP 是否被封禁constblockedawaitcheckBlockedIP(ip)if(blocked){returnnavigateTo(/blocked)}}})constcheckBlockedIPasync(ip:string):Promiseboolean{// 实际项目中可以从数据库或 Redis 查询constblockedIPs[192.168.1.100,10.0.0.50]returnblockedIPs.includes(ip)}七、API 请求拦截服务端 API 路由也可以用中间件// server/middleware/auth.tsexportdefaultdefineEventHandler(async(event){consturlgetRequestURL(event)// 只拦截需要认证的接口if(!url.pathname.startsWith(/api/protected/)){return}consttokengetHeader(event,Authorization)?.replace(Bearer ,)if(!token){throwcreateError({statusCode:401,message:Unauthorized})}try{constuserawaitverifyToken(token)event.context.useruser}catch{throwcreateError({statusCode:401,message:Invalid token})}})API 接口中使用// server/api/protected/profile.tsexportdefaultdefineEventHandler((event){constuserevent.context.userreturn{id:user.id,name:user.name,email:user.email}})八、请求限流防止接口被滥用// server/middleware/rate-limit.tsconstrequestsnewMapstring,number[]()exportdefaultdefineEventHandler((event){constipgetRequestIP(event)constnowDate.now()constwindowMs60*1000// 1 分钟constmaxRequests100// 最多 100 次请求// 获取该 IP 的请求记录constipRequestsrequests.get(ip)||[]// 过滤掉窗口外的请求constrecentRequestsipRequests.filter(timenow-timewindowMs)// 检查是否超限if(recentRequests.lengthmaxRequests){throwcreateError({statusCode:429,message:Too many requests})}// 记录本次请求recentRequests.push(now)requests.set(ip,recentRequests)})九、CORS 配置// server/middleware/cors.tsexportdefaultdefineEventHandler((event){constallowedOrigins[https://example.com,https://admin.example.com]constorigingetHeader(event,origin)||if(allowedOrigins.includes(origin)){setResponseHeaders(event,{Access-Control-Allow-Origin:origin,Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS,Access-Control-Allow-Headers:Content-Type, Authorization,Access-Control-Allow-Credentials:true})}// 处理预检请求if(getMethod(event)OPTIONS){setResponseStatus(event,204)return}})十、全局错误处理// server/middleware/error-handler.tsexportdefaultdefineEventHandler((event){// 设置错误处理event.node.res.on(finish,(){conststatusgetResponseStatus(event)if(status400){consturlgetRequestURL(event)console.error(Error${status}:${url})// 发送到错误监控服务}})})总结中间件高级用法场景实现方式登录检查全局中间件 token 判断角色权限to.meta.role 权限比较数据预加载中间件中调用 store 方法访问日志全局中间件 异步上报IP 黑名单服务端中间件 IP 检查API 拦截server/middleware/请求限流Map 记录 时间窗口下一篇聊聊插件系统学习如何扩展 Nuxt 能力。相关文章入门篇三Nuxt4组件自动导入写代码少敲一半字入门篇二Nuxt 4路由自动生成告别手动配置路由的日子延伸阅读nuxt4完整系列持续更新中。。欢迎来逛逛内容有帮助点赞、收藏、关注三连评论区等你