6.4 KiB
6.4 KiB
Nova Admin 登录鉴权系统文档
概述
Nova Admin 采用基于 JWT Token 的登录鉴权机制,通过 Pinia Store 管理认证状态,结合路由守卫实现完整的身份验证和访问控制。
🏗️ 架构设计
核心组件
- 认证状态管理 (
src/store/auth.ts) - 路由守卫 (
src/router/guard.ts) - 登录页面 (
src/views/login/) - API 接口 (
src/service/api/login.ts) - 本地存储工具 (
src/utils/storage.ts)
🔐 认证流程
1. 登录流程
sequenceDiagram
participant U as 用户
participant L as 登录页面
participant A as AuthStore
participant API as 后端API
participant R as RouteStore
participant Router as 路由系统
U->>L: 输入用户名密码
L->>A: authStore.login(username, password)
A->>API: fetchLogin(credentials)
API-->>A: 返回用户信息和Token
A->>A: 保存Token和用户信息到localStorage
A->>R: routeStore.initAuthRoute()
R->>R: 初始化用户路由和菜单
A->>Router: 重定向到首页或redirect页面
2. 登出流程
sequenceDiagram
participant U as 用户
participant A as AuthStore
participant R as RouteStore
participant T as TabStore
participant Router as 路由系统
U->>A: authStore.logout()
A->>A: 清除本地存储(Token, userInfo)
A->>R: routeStore.resetRouteStore()
A->>T: tabStore.clearAllTabs()
A->>A: 重置Store状态
A->>Router: 重定向到登录页
📁 文件结构详解
AuthStore (src/store/auth.ts)
负责管理用户认证状态和相关操作:
状态管理
interface AuthStatus {
userInfo: Api.Login.Info | null // 用户信息
token: string // 访问令牌
}
核心方法
login(userName, password): 执行登录操作logout(): 执行登出操作handleLoginInfo(data): 处理登录成功后的数据clearAuthStorage(): 清除本地认证存储
计算属性
isLogin: 基于 token 判断用户是否已登录
登录页面组件
主要文件
src/views/login/index.vue- 登录页面容器src/views/login/components/Login/index.vue- 登录表单组件src/views/login/components/Register/index.vue- 注册组件src/views/login/components/ResetPwd/index.vue- 重置密码组件
登录表单特性
- 表单验证(用户名和密码必填)
- 记住密码功能
- 加载状态提示
- 国际化支持
API 接口 (src/service/api/login.ts)
核心接口
// 用户登录
fetchLogin(data: { userName: string, password: string })
// 刷新Token
fetchUpdateToken(data: any)
// 获取用户路由
fetchUserRoutes(params: { id: number })
🛡️ 数据存储
localStorage 存储项
| 键名 | 说明 | 数据类型 |
|---|---|---|
accessToken |
访问令牌 | string |
refreshToken |
刷新令牌 | string |
userInfo |
用户信息 | Api.Login.Info |
loginAccount |
记住的登录账号 | {account: string, pwd: string} |
用户信息结构
interface Api.Login.Info {
accessToken: string
refreshToken: string
id: number
userName: string
role: Entity.RoleType[] // 用户角色数组
// ... 其他用户信息
}
🔒 安全机制
Token 管理
-
双Token机制
accessToken: 用于API请求认证refreshToken: 用于刷新访问令牌
-
Token 存储
- 使用 localStorage 持久化存储
- 页面刷新后自动恢复登录状态
-
Token 验证
- 路由守卫检查 Token 有效性
- API 请求自动携带 Token
密码安全
-
前端验证
- 必填验证
- 格式验证(可扩展)
-
后端安全
- 密码加密存储(由后端实现)
- 登录失败次数限制(由后端实现)
🚦 路由保护
认证检查
路由守卫在 beforeEach 钩子中执行认证检查:
// 判断有无TOKEN,登录鉴权
const isLogin = Boolean(local.get('accessToken'))
if (to.meta.requiresAuth === true && !isLogin) {
const redirect = to.name === '404' ? undefined : to.fullPath
next({ path: '/login', query: { redirect } })
return
}
重定向机制
- 未登录访问受保护路由: 重定向到登录页,并保存原始路由
- 登录成功: 重定向到原始路由或默认首页
- 已登录访问登录页: 重定向到首页
🛠️ 开发指南
添加新的认证检查
- 在路由元信息中设置认证要求:
{
path: '/protected',
meta: {
requiresAuth: true // 需要登录
}
}
- 在组件中检查登录状态:
import { useAuthStore } from '@/store'
const authStore = useAuthStore()
if (!authStore.isLogin) {
// 处理未登录状态
}
自定义登录逻辑
可以通过扩展 AuthStore 的 login 方法来实现自定义登录逻辑:
// 扩展登录验证
async login(userName: string, password: string, captcha?: string) {
try {
// 添加验证码验证
if (this.needCaptcha && !captcha) {
throw new Error('需要验证码')
}
const { isSuccess, data } = await fetchLogin({
userName,
password,
captcha
})
if (!isSuccess) return
await this.handleLoginInfo(data)
} catch (e) {
console.warn('[Login Error]:', e)
}
}
🔧 配置项
环境变量
VITE_ROUTE_LOAD_MODE: 路由加载模式(static/dynamic)VITE_HOME_PATH: 登录成功后的默认首页路径
默认配置
// 默认登录账号(开发环境)
const formValue = ref({
account: 'admin',
pwd: '123456',
})
🚨 常见问题
1. Token 过期处理
系统会在请求拦截器中自动处理 Token 过期:
- 检测到 Token 过期
- 自动调用刷新 Token 接口
- 重新发送原始请求
2. 路由初始化时机
确保在路由守卫中正确初始化路由:
if (!routeStore.isInitAuthRoute) {
await routeStore.initAuthRoute()
// 处理 404 重新导航
if (to.name === '404') {
next({ path: to.fullPath, replace: true })
return
}
}
3. 登录状态丢失
检查以下几点:
- localStorage 是否被清除
- Token 是否过期
- 网络请求是否正常