Files
whale-town-front/scripts/managers/AuthManager.gd
lzdFeiFei d623c705b6 feat:实现登录系统和用户认证功能
- 添加登录场景(login_scene.tscn)和主菜单场景(main_menu_scene.tscn)
- 实现认证管理器(AuthManager)用于用户登录和会话管理
- 添加核心服务:加密服务、存储服务、网络服务
- 配置项目主场景为登录场景
- 添加自动加载服务到项目配置
- 添加开发环境配置(VSCode、Claude)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 01:15:33 +08:00

184 lines
4.5 KiB
GDScript
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.
extends Node
## 认证管理器
## 统一管理用户登录、登出、Token等认证相关功能
# 登录状态枚举
enum LoginState {
NOT_LOGGED_IN, # 未登录
LOGGING_IN, # 登录中
LOGGED_IN, # 已登录
GUEST # 游客模式
}
# 信号
signal login_success(userData: UserData)
signal login_failed(errorCode: int, errorMessage: String)
signal logout_success()
# 当前登录状态
var currentState: LoginState = LoginState.NOT_LOGGED_IN
# Token
var accessToken: String = ""
var tokenExpireTime: int = 0
# 当前用户信息
var currentUser: UserData = null
# 是否正在登录(防止重复请求)
var _isLoggingIn: bool = false
func _ready():
# 游戏启动时尝试从本地加载 Token 和用户信息
_tryLoadLocalAuth()
## 登录
func login(username: String, password: String, rememberPassword: bool) -> Dictionary:
# 防止重复登录
if _isLoggingIn:
return {
"success": false,
"error_code": ErrorCode.INVALID_INPUT,
"message": "登录中,请稍候..."
}
_isLoggingIn = true
currentState = LoginState.LOGGING_IN
# 构建登录请求数据
var requestData = {
"identifier": username,
"password": password
}
# 发送登录请求
var response = await NetworkService.post("/api/auth/login", requestData)
_isLoggingIn = false
# 处理响应
if response.success:
# 解析用户数据和 Token
var data = response.get("data", {})
var token = data.get("access_token", "")
var userData = data.get("user", {})
if token.is_empty():
var errorMsg = "服务器返回数据格式错误"
login_failed.emit(ErrorCode.SERVER_ERROR, errorMsg)
currentState = LoginState.NOT_LOGGED_IN
return {
"success": false,
"error_code": ErrorCode.SERVER_ERROR,
"message": errorMsg
}
# 保存 Token
accessToken = token
tokenExpireTime = int(Time.get_unix_time_from_system()) + 3600 * 24 # 假设24小时过期
StorageService.saveToken(accessToken, tokenExpireTime)
# 保存用户信息
currentUser = UserData.fromDict(userData)
StorageService.saveUserData(currentUser)
# 如果勾选记住密码,保存账号密码
if rememberPassword:
StorageService.saveAccount(username, password, true)
else:
# 只保存用户名,不保存密码
StorageService.save("account", "last_username", username)
StorageService.clearSavedPassword()
# 更新状态
currentState = LoginState.LOGGED_IN
# 发送登录成功信号
login_success.emit(currentUser)
return {
"success": true,
"message": "登录成功",
"user": currentUser
}
else:
# 登录失败
var errorCode = response.get("error_code", ErrorCode.WRONG_CREDENTIALS)
var errorMsg = response.get("message", "登录失败")
currentState = LoginState.NOT_LOGGED_IN
login_failed.emit(errorCode, errorMsg)
return {
"success": false,
"error_code": errorCode,
"message": errorMsg
}
## 登出
func logout() -> void:
# 清除 Token 和用户信息
accessToken = ""
tokenExpireTime = 0
currentUser = null
# 清除本地存储(保留用户名和记住密码设置)
StorageService.clearToken()
# 更新状态
currentState = LoginState.NOT_LOGGED_IN
# 发送登出成功信号
logout_success.emit()
print("用户已登出")
## 检查是否已登录
func isLoggedIn() -> bool:
return currentState == LoginState.LOGGED_IN and currentUser != null
## 获取当前用户
func getCurrentUser() -> UserData:
return currentUser
## 获取当前 Token
func getToken() -> String:
return accessToken
## 尝试从本地加载认证信息
func _tryLoadLocalAuth() -> void:
# 加载 Token
var tokenData = StorageService.loadToken()
var token = tokenData.get("token", "")
var expireTime = tokenData.get("expire_time", 0)
# 检查 Token 是否有效
var currentTime = int(Time.get_unix_time_from_system())
if token.is_empty() or expireTime <= currentTime:
print("本地 Token 无效或已过期")
return
# Token 有效,加载用户信息
var userData = StorageService.loadUserData()
if userData == null:
print("本地用户信息不存在")
return
# 恢复登录状态
accessToken = token
tokenExpireTime = expireTime
currentUser = userData
currentState = LoginState.LOGGED_IN
print("从本地恢复登录状态: ", currentUser.username)
# 可选:静默刷新 Token如果接近过期
# _refreshTokenIfNeeded()
## 检查 Token 是否即将过期
func isTokenExpiring() -> bool:
var currentTime = int(Time.get_unix_time_from_system())
var timeLeft = tokenExpireTime - currentTime
return timeLeft < 300 # 少于5分钟