1
This commit is contained in:
316
utils/auth.js
Normal file
316
utils/auth.js
Normal file
@@ -0,0 +1,316 @@
|
||||
/**
|
||||
* 用户认证和权限管理系统
|
||||
*/
|
||||
|
||||
const { Storage } = require('./storage.js')
|
||||
const { logger } = require('./logger.js')
|
||||
const { store } = require('./store.js')
|
||||
|
||||
class AuthManager {
|
||||
constructor() {
|
||||
this.token = null
|
||||
this.userInfo = null
|
||||
this.permissions = []
|
||||
this.init()
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
init() {
|
||||
this.token = Storage.get('token')
|
||||
this.userInfo = Storage.get('userInfo')
|
||||
this.permissions = Storage.get('permissions', [])
|
||||
|
||||
if (this.token && this.userInfo) {
|
||||
store.setState({
|
||||
isLogin: true,
|
||||
userInfo: this.userInfo
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信登录
|
||||
*/
|
||||
async wxLogin() {
|
||||
try {
|
||||
// 1. 获取微信登录code
|
||||
const { code } = await this._wxLogin()
|
||||
logger.info('微信登录code获取成功', { code })
|
||||
|
||||
// 2. 获取用户信息
|
||||
const userInfo = await this._getUserProfile()
|
||||
logger.info('用户信息获取成功', { userInfo })
|
||||
|
||||
// 3. 调用后端登录接口
|
||||
// TODO: 替换为实际的后端登录接口
|
||||
const response = await this._mockLogin(code, userInfo)
|
||||
|
||||
// 4. 保存登录状态
|
||||
this.setAuth(response.token, response.userInfo, response.permissions)
|
||||
|
||||
logger.info('登录成功', { userId: response.userInfo.id })
|
||||
|
||||
return response
|
||||
} catch (error) {
|
||||
logger.error('登录失败', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信登录 - 获取code
|
||||
*/
|
||||
_wxLogin() {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.login({
|
||||
success: resolve,
|
||||
fail: reject
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
_getUserProfile() {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.getUserProfile({
|
||||
desc: '用于完善用户资料',
|
||||
success: (res) => resolve(res.userInfo),
|
||||
fail: reject
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟登录(开发用)
|
||||
*/
|
||||
async _mockLogin(code, userInfo) {
|
||||
// TODO: 替换为实际的API调用
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
token: 'mock_token_' + Date.now(),
|
||||
userInfo: {
|
||||
id: Math.random().toString(36).substr(2, 9),
|
||||
nickName: userInfo.nickName,
|
||||
avatarUrl: userInfo.avatarUrl,
|
||||
studentId: '2021001',
|
||||
grade: '2021级',
|
||||
major: '计算机科学与技术',
|
||||
email: 'student@example.com'
|
||||
},
|
||||
permissions: ['user', 'student']
|
||||
})
|
||||
}, 500)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置认证信息
|
||||
*/
|
||||
setAuth(token, userInfo, permissions = []) {
|
||||
this.token = token
|
||||
this.userInfo = userInfo
|
||||
this.permissions = permissions
|
||||
|
||||
Storage.set('token', token)
|
||||
Storage.set('userInfo', userInfo)
|
||||
Storage.set('permissions', permissions)
|
||||
|
||||
store.setState({
|
||||
isLogin: true,
|
||||
userInfo: userInfo
|
||||
})
|
||||
|
||||
logger.info('认证信息已保存')
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
logout() {
|
||||
this.token = null
|
||||
this.userInfo = null
|
||||
this.permissions = []
|
||||
|
||||
Storage.remove('token')
|
||||
Storage.remove('userInfo')
|
||||
Storage.remove('permissions')
|
||||
|
||||
store.setState({
|
||||
isLogin: false,
|
||||
userInfo: null
|
||||
})
|
||||
|
||||
logger.info('已退出登录')
|
||||
|
||||
wx.showToast({
|
||||
title: '已退出登录',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否登录
|
||||
*/
|
||||
isLogin() {
|
||||
return !!this.token && !!this.userInfo
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
getUserInfo() {
|
||||
return this.userInfo
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Token
|
||||
*/
|
||||
getToken() {
|
||||
return this.token
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查权限
|
||||
*/
|
||||
hasPermission(permission) {
|
||||
return this.permissions.includes(permission)
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查多个权限(需要全部满足)
|
||||
*/
|
||||
hasAllPermissions(permissions) {
|
||||
return permissions.every(p => this.hasPermission(p))
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查多个权限(满足任一即可)
|
||||
*/
|
||||
hasAnyPermission(permissions) {
|
||||
return permissions.some(p => this.hasPermission(p))
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户信息
|
||||
*/
|
||||
async updateUserInfo(updates) {
|
||||
try {
|
||||
// TODO: 调用后端API更新用户信息
|
||||
const updatedUserInfo = { ...this.userInfo, ...updates }
|
||||
|
||||
this.userInfo = updatedUserInfo
|
||||
Storage.set('userInfo', updatedUserInfo)
|
||||
store.setState({ userInfo: updatedUserInfo })
|
||||
|
||||
logger.info('用户信息更新成功', updates)
|
||||
|
||||
wx.showToast({
|
||||
title: '更新成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
return updatedUserInfo
|
||||
} catch (error) {
|
||||
logger.error('用户信息更新失败', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新Token
|
||||
*/
|
||||
async refreshToken() {
|
||||
try {
|
||||
// TODO: 调用后端API刷新token
|
||||
const newToken = 'new_token_' + Date.now()
|
||||
|
||||
this.token = newToken
|
||||
Storage.set('token', newToken)
|
||||
|
||||
logger.info('Token刷新成功')
|
||||
|
||||
return newToken
|
||||
} catch (error) {
|
||||
logger.error('Token刷新失败', error)
|
||||
this.logout()
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面权限守卫
|
||||
*/
|
||||
class RouteGuard {
|
||||
/**
|
||||
* 检查页面访问权限
|
||||
*/
|
||||
static check(requiredPermissions = []) {
|
||||
const authManager = new AuthManager()
|
||||
|
||||
// 检查是否登录
|
||||
if (!authManager.isLogin()) {
|
||||
wx.showModal({
|
||||
title: '提示',
|
||||
content: '请先登录',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.navigateTo({
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
} else {
|
||||
wx.navigateBack()
|
||||
}
|
||||
}
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查权限
|
||||
if (requiredPermissions.length > 0) {
|
||||
if (!authManager.hasAllPermissions(requiredPermissions)) {
|
||||
wx.showToast({
|
||||
title: '没有访问权限',
|
||||
icon: 'none'
|
||||
})
|
||||
wx.navigateBack()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面装饰器
|
||||
*/
|
||||
static requireAuth(requiredPermissions = []) {
|
||||
return function(target) {
|
||||
const originalOnLoad = target.prototype.onLoad
|
||||
|
||||
target.prototype.onLoad = function(options) {
|
||||
if (RouteGuard.check(requiredPermissions)) {
|
||||
if (originalOnLoad) {
|
||||
originalOnLoad.call(this, options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建全局实例
|
||||
const authManager = new AuthManager()
|
||||
|
||||
module.exports = {
|
||||
AuthManager,
|
||||
authManager,
|
||||
RouteGuard
|
||||
}
|
||||
Reference in New Issue
Block a user