appointment_system/docs/guides/AUTH_GUIDE.md
2025-12-19 00:37:31 +08:00

389 lines
7.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 认证系统使用指南
本文档说明如何在项目中使用认证系统。
## 认证流程
### 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)