探索 Nuxt.js 全栈能力:用 Better-Auth 打造类型安全的 RBAC 权限系统

☘️ 前言

Hello,感觉已经很久没有认真写文章了。自从 AI 热潮席卷技术圈之后,传统的技术路线文章似乎渐渐失去了原本的参考意义。

这次项目的开发初衷,其实是对 Better Auth 很感兴趣,想借助一个全新项目来系统学习它。在技术选型阶段,我在 Next.jsNuxt.js 之间犹豫了一下。不过考虑到自己之前已经用 Next.js 做过不少项目,比较熟悉,而且工作中也主要使用 React 相关技术栈,所以这次决定尝试点不一样的,最终选择了 Nuxt.js

原本的计划只是实现一个基础的鉴权模块,包括登录、注册这些核心功能。但随着开发的推进,又觉得动态菜单和权限配置也应该一并加上,于是功能越做越多,不知不觉就发展成了现在这个规模。如果大家有兴趣,欢迎去看看,也欢迎交流讨论。

📚 项目简介

Better Nuxt 是一个现代化的全栈后台管理系统,前端基于 Nuxt.jsNuxt UI 构建,后端采用 Better-Auth 认证框架与 Drizzle ORM 配合 PostgreSQL 数据库实现。

本项目集成了当前流行的前后端技术栈,是学习全栈开发和现代认证授权的理想参考项目。

✨ 特性

🚀 现代化全栈架构

  • 前沿技术 :深度整合 Nuxt 3Better-AuthNuxt UIDrizzlePostgreSQL,紧跟现代 Web 技术趋势。

  • 极致性能SSR/SSG 混合渲染、高效数据库查询优化,兼顾 SEO 与用户体验。

  • 安全可靠:内置完备认证体系,结合强类型定义,从源头降低运行时错误。

🔐 开箱即用的认证系统

集成 Better-auth,支持多策略身份验证、会话管理与权限控制,为应用提供安全可靠的用户体系

|----------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| | | | |

🎨 可视化主题配置中心

内置 18 种主题主色、明暗模式、圆角档位与路由动画,满足多品牌与个性化展示需求

🌐 国际化支持

多语言(中/英)一键切换,通过后台可视化管理配置,灵活适配企业级后台与多地域业务场景

🛡️ 细粒度权限与动态菜单系统

集成角色权限(RBAC)、动态菜单生成、按钮级权限控制,前后端统一鉴权,精准管控每个操作节点

当用户登录后,后端需要查询聚合数据:

  1. 通过 userRoles 找到用户关联的所有 roleId

  2. 通过 roleMenus 找到这些角色关联的所有 menuId

  3. 权限合并规则:如果用户拥有多个角色,且多个角色都拥有同一个菜单的权限,则权限位 permissions 取最大值(按位或运算 |)。

权限位(Bitmask)的计算与判断,假设我们定义了以下权限常量:

ts 复制代码
    // 建议使用 2 的幂次方
    export const PERMISSIONS = {
      VIEW: 1 << 0, // 1 -> 查看
      CREATE: 1 << 1, // 2 -> 新增
      EDIT: 1 << 2, // 4 -> 编辑
      DELETE: 1 << 3, // 8 -> 删除
      EXPORT: 1 << 4, // 16 -> 导出
    };

如何在业务代码中判断是否有某个权限:

ts 复制代码
    // 假设从数据库查出的 role_menus.permissions 为 7 (意味着包含 1+2+4,即 查看+新增+编辑)
    const userPermissions = 7; 

    // 检查是否有 "删除" 权限 (8)
    const canDelete = (userPermissions & PERMISSIONS.DELETE) === PERMISSIONS.DELETE;
    // 结果:false (因为 7 & 8 = 0)

    // 检查是否有 "查看" 权限 (1)
    const canView = (userPermissions & PERMISSIONS.VIEW) === PERMISSIONS.VIEW;
    // 结果:true (因为 7 & 1 = 1)

注意点:PostgreSQL 的 integer 类型是 32位有符号整数,最大值为 2,147,483,647(即231−1),这意味着您最多只能定义 31 个不同的权限位(0 到 30)。

🔄 智能版本更新提示

内置 nuxt-skew-protection 版本检测机制,自动提示用户刷新获取最新版本,避免旧版本缓存导致功能不一致问题:nuxt-skew-protection

核心代码:

html 复制代码
    <SkewNotification v-slot="{ isCurrentChunksOutdated, dismiss, reload, timeAgo }">
        <Transition
          enter-active-class="transition duration-300 ease-out"
          enter-from-class="opacity-0 translate-y-2"
          enter-to-class="opacity-100 translate-y-0"
          leave-active-class="transition duration-200 ease-in"
          leave-from-class="opacity-100 translate-y-0"
          leave-to-class="opacity-0 translate-y-2"
        >
          <div v-if="isCurrentChunksOutdated" class="fixed bottom-4 right-4 z-50">
            <div class="flex items-center gap-3 bg-white dark:bg-gray-900 rounded-full shadow-lg ring-1 ring-gray-200 dark:ring-gray-800 px-4 py-3">
              <span class="text-lg">✨</span>
              <div class="text-sm font-medium">
                检测到新版本! {{ timeAgo }}
              </div>
              <UButton color="primary" size="xs" :label="i18nCommon('reload')" icon="lucide:refresh-cw" @click="reload" />
              <UButton color="neutral" variant="ghost" size="xs" icon="i-heroicons-x-mark-20-solid" @click="dismiss" />
            </div>
          </div>
        </Transition>
      </SkewNotification>

示例:

🛠️ 技术栈

📂 文件目录

csharp 复制代码
better-nuxt/
├── .nuxt/                  # Nuxt 自动生成的构建目录(通常不需要手动修改)
├── app/ 
    └── assets/                 # 静态资源目录(未编译的样式、图片、字体等)
    └── components/             # Vue 组件目录(支持自动导入)
    └── composables/            # 组合式 API 目录(自动导入)
    └── layouts/                # 布局组件目录(如 DefaultLayout, AuthLayout)
    └── middleware/             # 中间件目录(路由守卫、权限校验等)
    └── pages/                  # 页面视图目录(基于文件系统的路由)
├── public/                 # 静态资源目录(不经过打包处理,如 robots.txt, favicon.ico)
├── server/                 # 后端 API 服务目录(Nuxt Nitro Server)
│   └── api/                # API 路由接口
│   └── middleware/         # 服务器端中间件
├── .env                    # 环境变量配置文件(注意勿提交至版本库)
├── .gitignore              # Git 忽略文件配置
├── app.config.ts           # 应用配置文件
├── auth-schema.ts          # Better-Auth 认证相关 Schema 定义
├── CHANGELOG.md            # 版本更新日志
├── commitlint.config.js    # Commit 提交规范校验配置
├── drizzle.config.ts       # Drizzle ORM 配置文件
├── eslint.config.mjs       # ESLint 代码规范配置文件
├── LICENSE                 # 开源许可证文件
├── nuxt.config.ts          # Nuxt 核心配置文件
├── package.json            # 项目依赖及脚本管理文件
├── package-lock.json       # 依赖版本锁定文件
├── README.md               # 项目说明文档
└── tsconfig.json           # TypeScript 配置文件

🔐 RBAC 权限映射关系

🪴 演示图

|----------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| | |
| | |
| | |

🍄 总结

这次从鉴权入手,一路做到权限管理,虽然范围远超最初设想,但整个过程反而成了最好的学习方式------在真实场景中边做边学,遇到问题再倒逼自己去理解 Better Auth 的机制和 Nuxt.js 的生态。项目目前还在持续完善中,后续也会继续补充更多功能。如果你也在研究类似的技术方案,或者对 Better Auth 有兴趣,欢迎一起交流,也希望能给正在做技术选型的朋友一些参考。代码已开源,感兴趣的话欢迎 star 或提 issue,任何反馈都对我很有帮助。

  • 本项目未经严格测试,可能存在 Bug,欢迎反馈。

  • 本项目仅供学习交流,禁止用于商业用途。

Github:better-nuxt

线上预览:nuxt.baiwumm.com/

相关推荐
Awu12271 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
咪库咪库咪1 小时前
Vue3-生命周期
前端
莪_幻尘2 小时前
你的 AI Skill 越多越蠢?Token 上下文爆炸的求生指南
前端·ai编程
lichenyang4532 小时前
从 has.echo 到异步 API 注册表:一次 ASCF API 回调不触发的排查复盘
前端
林瞅瞅2 小时前
Nuxt3 项目部署 Nginx 防盗链后特定 JS 文件 403 问题修复方案
前端
kyriewen3 小时前
别再每次都 Google 了:我整理了前端日常最常踩的 10 个 Git 坑,附速查表
前端·javascript·git
一颗奇趣蛋3 小时前
Web 视频开发完全指南:从入门到精通
前端
非洲农业不发达3 小时前
windows终端体验大升级,让你拥有macos级别的美化
前端·后端
妙码生花3 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十七):登录接口完善,登录页接口整合,解决跨域
前端·后端·ai编程
唐诗4 小时前
改 3 行配置,我的 Tauri dev 冷启动从 100 秒干到 4 秒
前端·客户端