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

7.5 KiB
Raw Blame History

认证系统使用指南

本文档说明如何在项目中使用认证系统。

认证流程

1. 应用启动流程

应用启动
    ↓
进入首页 (pages/index/index.vue)
    ↓
检查 Token
    ↓
┌─────────────┬─────────────┐
│  Token 有效  │  Token 无效  │
└─────────────┴─────────────┘
       ↓              ↓
   显示首页      跳转登录页

2. 登录流程

用户点击登录
    ↓
获取微信 code
    ↓
调用后端登录接口
    ↓
保存 token 和用户信息
    ↓
跳转到首页

3. Token 验证流程

页面加载
    ↓
检查本地 token
    ↓
调用 GetUserProfile 接口验证
    ↓
┌─────────────┬─────────────┐
│   验证成功   │   验证失败   │
└─────────────┴─────────────┘
       ↓              ↓
  更新用户信息    清除数据并跳转登录页

认证工具使用

引入认证工具

import { 
  isLoggedIn, 
  getCurrentUser, 
  requireAuth, 
  logout 
} from '@/utils/auth.js'

常用方法

1. 检查是否已登录

if (isLoggedIn()) {
  console.log('用户已登录')
} else {
  console.log('用户未登录')
}

2. 获取当前用户信息

const user = getCurrentUser()
if (user) {
  console.log('用户昵称:', user.nickname)
  console.log('用户头像:', user.avatar)
}

3. 要求登录(未登录则跳转)

// 在需要登录的页面中使用
onLoad() {
  // 检查登录状态,未登录则跳转到登录页
  if (!requireAuth()) {
    return // 未登录,已跳转
  }
  
  // 已登录,继续执行
  this.loadData()
}

4. 登出

async handleLogout() {
  uni.showModal({
    title: '提示',
    content: '确定要退出登录吗?',
    success: async (res) => {
      if (res.confirm) {
        await logout()
      }
    }
  })
}

5. 验证 Token

import { validateToken } from '@/utils/auth.js'

async checkToken() {
  const isValid = await validateToken()
  if (isValid) {
    console.log('Token 有效')
  } else {
    console.log('Token 无效')
  }
}

6. 刷新 Token

import { refreshToken } from '@/utils/auth.js'

async refreshAuthToken() {
  const success = await refreshToken()
  if (success) {
    console.log('Token 刷新成功')
  } else {
    console.log('Token 刷新失败')
  }
}

在页面中使用

示例 1: 需要登录的页面

<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: 个人中心页面

<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: 条件显示登录按钮

<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>

全局数据访问

在页面中访问全局用户数据

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无需手动处理

import { AppServer } from '@/modules/api/AppServer'

const appServer = new AppServer()

// 自动携带 token
const result = await appServer.GetUserProfile()

错误处理

Token 过期处理

当 API 返回 401 错误时,说明 token 已过期:

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 跳转登录页,确保页面栈清空

调试技巧

查看当前登录状态

console.log('Token:', uni.getStorageSync('token'))
console.log('User:', uni.getStorageSync('user'))
console.log('RefreshToken:', uni.getStorageSync('refreshToken'))

清除登录状态(用于测试)

import { clearAuthData } from '@/utils/auth.js'

// 清除所有认证数据
clearAuthData()

// 跳转到登录页
uni.reLaunch({ url: '/pages/login/login-page' })

模拟登录(用于开发测试)

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 失败时,可以选择不跳转登录页,而是显示错误提示。

相关文档