389 lines
7.5 KiB
Markdown
389 lines
7.5 KiB
Markdown
# 认证系统使用指南
|
||
|
||
本文档说明如何在项目中使用认证系统。
|
||
|
||
## 认证流程
|
||
|
||
### 1. 应用启动流程
|
||
|
||
```
|
||
应用启动
|
||
↓
|
||
进入首页 (pages/index/index.vue)
|
||
↓
|
||
检查 Token
|
||
↓
|
||
┌─────────────┬─────────────┐
|
||
│ Token 有效 │ Token 无效 │
|
||
└─────────────┴─────────────┘
|
||
↓ ↓
|
||
显示首页 跳转登录页
|
||
```
|
||
|
||
### 2. 登录流程
|
||
|
||
```
|
||
用户点击登录
|
||
↓
|
||
获取微信 code
|
||
↓
|
||
调用后端登录接口
|
||
↓
|
||
保存 token 和用户信息
|
||
↓
|
||
跳转到首页
|
||
```
|
||
|
||
### 3. Token 验证流程
|
||
|
||
```
|
||
页面加载
|
||
↓
|
||
检查本地 token
|
||
↓
|
||
调用 GetUserProfile 接口验证
|
||
↓
|
||
┌─────────────┬─────────────┐
|
||
│ 验证成功 │ 验证失败 │
|
||
└─────────────┴─────────────┘
|
||
↓ ↓
|
||
更新用户信息 清除数据并跳转登录页
|
||
```
|
||
|
||
## 认证工具使用
|
||
|
||
### 引入认证工具
|
||
|
||
```javascript
|
||
import {
|
||
isLoggedIn,
|
||
getCurrentUser,
|
||
requireAuth,
|
||
logout
|
||
} from '@/utils/auth.js'
|
||
```
|
||
|
||
### 常用方法
|
||
|
||
#### 1. 检查是否已登录
|
||
|
||
```javascript
|
||
if (isLoggedIn()) {
|
||
console.log('用户已登录')
|
||
} else {
|
||
console.log('用户未登录')
|
||
}
|
||
```
|
||
|
||
#### 2. 获取当前用户信息
|
||
|
||
```javascript
|
||
const user = getCurrentUser()
|
||
if (user) {
|
||
console.log('用户昵称:', user.nickname)
|
||
console.log('用户头像:', user.avatar)
|
||
}
|
||
```
|
||
|
||
#### 3. 要求登录(未登录则跳转)
|
||
|
||
```javascript
|
||
// 在需要登录的页面中使用
|
||
onLoad() {
|
||
// 检查登录状态,未登录则跳转到登录页
|
||
if (!requireAuth()) {
|
||
return // 未登录,已跳转
|
||
}
|
||
|
||
// 已登录,继续执行
|
||
this.loadData()
|
||
}
|
||
```
|
||
|
||
#### 4. 登出
|
||
|
||
```javascript
|
||
async handleLogout() {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定要退出登录吗?',
|
||
success: async (res) => {
|
||
if (res.confirm) {
|
||
await logout()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
```
|
||
|
||
#### 5. 验证 Token
|
||
|
||
```javascript
|
||
import { validateToken } from '@/utils/auth.js'
|
||
|
||
async checkToken() {
|
||
const isValid = await validateToken()
|
||
if (isValid) {
|
||
console.log('Token 有效')
|
||
} else {
|
||
console.log('Token 无效')
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 6. 刷新 Token
|
||
|
||
```javascript
|
||
import { refreshToken } from '@/utils/auth.js'
|
||
|
||
async refreshAuthToken() {
|
||
const success = await refreshToken()
|
||
if (success) {
|
||
console.log('Token 刷新成功')
|
||
} else {
|
||
console.log('Token 刷新失败')
|
||
}
|
||
}
|
||
```
|
||
|
||
## 在页面中使用
|
||
|
||
### 示例 1: 需要登录的页面
|
||
|
||
```vue
|
||
<template>
|
||
<view class="page">
|
||
<view v-if="user">
|
||
<text>欢迎,{{ user.nickname }}</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { requireAuth, getCurrentUser } from '@/utils/auth.js'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
user: null
|
||
}
|
||
},
|
||
onLoad() {
|
||
// 检查登录状态
|
||
if (!requireAuth()) {
|
||
return
|
||
}
|
||
|
||
// 获取用户信息
|
||
this.user = getCurrentUser()
|
||
}
|
||
}
|
||
</script>
|
||
```
|
||
|
||
### 示例 2: 个人中心页面
|
||
|
||
```vue
|
||
<template>
|
||
<view class="page">
|
||
<view class="user-info">
|
||
<image :src="user.avatar" class="avatar"></image>
|
||
<text class="nickname">{{ user.nickname }}</text>
|
||
</view>
|
||
|
||
<button @click="handleLogout">退出登录</button>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { getCurrentUser, logout } from '@/utils/auth.js'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
user: null
|
||
}
|
||
},
|
||
onLoad() {
|
||
this.user = getCurrentUser()
|
||
},
|
||
methods: {
|
||
async handleLogout() {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定要退出登录吗?',
|
||
success: async (res) => {
|
||
if (res.confirm) {
|
||
await logout()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
```
|
||
|
||
### 示例 3: 条件显示登录按钮
|
||
|
||
```vue
|
||
<template>
|
||
<view class="page">
|
||
<button v-if="!isLoggedIn" @click="goToLogin">登录</button>
|
||
<view v-else>
|
||
<text>已登录</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { isLoggedIn } from '@/utils/auth.js'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
isLoggedIn: false
|
||
}
|
||
},
|
||
onShow() {
|
||
this.isLoggedIn = isLoggedIn()
|
||
},
|
||
methods: {
|
||
goToLogin() {
|
||
uni.navigateTo({
|
||
url: '/pages/login/login-page'
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
```
|
||
|
||
## 全局数据访问
|
||
|
||
### 在页面中访问全局用户数据
|
||
|
||
```javascript
|
||
const app = getApp()
|
||
|
||
// 获取 token
|
||
const token = app.globalData.token
|
||
|
||
// 获取用户信息
|
||
const user = app.globalData.user
|
||
|
||
// 检查是否需要刷新
|
||
if (app.globalData.shouldRefresh) {
|
||
// 执行刷新操作
|
||
this.refreshData()
|
||
app.globalData.shouldRefresh = false
|
||
}
|
||
```
|
||
|
||
## API 请求中的认证
|
||
|
||
AppServer 会自动在请求头中添加 Authorization,无需手动处理:
|
||
|
||
```javascript
|
||
import { AppServer } from '@/modules/api/AppServer'
|
||
|
||
const appServer = new AppServer()
|
||
|
||
// 自动携带 token
|
||
const result = await appServer.GetUserProfile()
|
||
```
|
||
|
||
## 错误处理
|
||
|
||
### Token 过期处理
|
||
|
||
当 API 返回 401 错误时,说明 token 已过期:
|
||
|
||
```javascript
|
||
const result = await appServer.GetUserProfile()
|
||
|
||
if (!result.success && result.error?.code === 'UNAUTHORIZED') {
|
||
// Token 过期,尝试刷新
|
||
const refreshSuccess = await refreshToken()
|
||
|
||
if (refreshSuccess) {
|
||
// 刷新成功,重试请求
|
||
const retryResult = await appServer.GetUserProfile()
|
||
} else {
|
||
// 刷新失败,跳转登录页
|
||
clearAuthData()
|
||
uni.reLaunch({ url: '/pages/login/login-page' })
|
||
}
|
||
}
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **首页自动检查**: 首页会自动检查登录状态,无需手动调用
|
||
2. **Token 格式**: Token 格式为 `Bearer <token>`
|
||
3. **本地存储**: Token 和用户信息同时存储在 localStorage 和 globalData
|
||
4. **登出清理**: 登出时会清除所有认证相关数据
|
||
5. **页面刷新**: 使用 `reLaunch` 跳转登录页,确保页面栈清空
|
||
|
||
## 调试技巧
|
||
|
||
### 查看当前登录状态
|
||
|
||
```javascript
|
||
console.log('Token:', uni.getStorageSync('token'))
|
||
console.log('User:', uni.getStorageSync('user'))
|
||
console.log('RefreshToken:', uni.getStorageSync('refreshToken'))
|
||
```
|
||
|
||
### 清除登录状态(用于测试)
|
||
|
||
```javascript
|
||
import { clearAuthData } from '@/utils/auth.js'
|
||
|
||
// 清除所有认证数据
|
||
clearAuthData()
|
||
|
||
// 跳转到登录页
|
||
uni.reLaunch({ url: '/pages/login/login-page' })
|
||
```
|
||
|
||
### 模拟登录(用于开发测试)
|
||
|
||
```javascript
|
||
import { saveAuthData } from '@/utils/auth.js'
|
||
|
||
// 保存测试数据
|
||
saveAuthData(
|
||
'Bearer test-token',
|
||
'test-refresh-token',
|
||
{
|
||
id: 'test-user-id',
|
||
nickname: '测试用户',
|
||
avatar: 'https://...'
|
||
}
|
||
)
|
||
```
|
||
|
||
## 常见问题
|
||
|
||
### Q: 为什么每次打开应用都要重新登录?
|
||
A: 检查 token 是否正确保存到 localStorage,确认 `saveAuthData` 方法被正确调用。
|
||
|
||
### Q: 如何在多个页面间共享用户信息?
|
||
A: 使用 `getCurrentUser()` 方法或访问 `getApp().globalData.user`。
|
||
|
||
### Q: Token 过期后如何自动刷新?
|
||
A: 使用 `refreshToken()` 方法,建议在 API 返回 401 时自动调用。
|
||
|
||
### Q: 如何实现"记住我"功能?
|
||
A: Token 默认会保存到 localStorage,下次打开应用会自动恢复。
|
||
|
||
### Q: 如何处理网络错误?
|
||
A: 在 `validateToken` 失败时,可以选择不跳转登录页,而是显示错误提示。
|
||
|
||
## 相关文档
|
||
|
||
- [API 使用指南](./modules/api/API_GUIDE.md)
|
||
- [配置指南](./CONFIG_GUIDE.md)
|
||
- [登录指南](./LOGIN_GUIDE.md)
|