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>
This commit is contained in:
2025-12-23 01:15:33 +08:00
parent 8ed260b413
commit d623c705b6
28 changed files with 1455 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
extends Node
## 加密服务
## 提供密码加密、解密等安全功能
# 固定的 Salt用于生成设备密钥
const FIXED_SALT: String = "whaleTown_2024_secret_key"
# AES 加密密钥基于设备ID生成
var _encryptionKey: PackedByteArray
func _ready():
_initEncryptionKey()
## 初始化加密密钥
func _initEncryptionKey() -> void:
# 使用设备唯一ID + 固定Salt 生成加密密钥
var deviceId = OS.get_unique_id()
var keyString = deviceId + FIXED_SALT
# 使用 SHA-256 生成 32 字节密钥
var crypto = Crypto.new()
var hash = crypto.generate_random_bytes(32) # 临时方案,实际应该用 hash
# 简单实现:取字符串的 MD5 哈希的前32字节
_encryptionKey = keyString.md5_buffer()
# 如果需要32字节重复一次
_encryptionKey.append_array(keyString.md5_buffer())
## 加密字符串(用于本地存储密码)
func encrypt(plainText: String) -> String:
if plainText.is_empty():
return ""
var crypto = Crypto.new()
var aes = AESContext.new()
# 生成随机 IV初始化向量
var iv = crypto.generate_random_bytes(16)
# 转换明文为字节
var plainBytes = plainText.to_utf8_buffer()
# 使用 AES-256-CBC 加密
aes.start(AESContext.MODE_CBC_ENCRYPT, _encryptionKey.slice(0, 32), iv)
var encryptedBytes = aes.update(plainBytes)
aes.finish()
# 将 IV 和加密数据组合IV + encrypted_data
var combined = PackedByteArray()
combined.append_array(iv)
combined.append_array(encryptedBytes)
# 转换为 Base64 字符串
return Marshalls.raw_to_base64(combined)
## 解密字符串
func decrypt(encryptedText: String) -> String:
if encryptedText.is_empty():
return ""
# Base64 解码
var combined = Marshalls.base64_to_raw(encryptedText)
if combined.size() < 16:
push_error("加密数据格式错误")
return ""
# 分离 IV 和加密数据
var iv = combined.slice(0, 16)
var encryptedBytes = combined.slice(16)
# 解密
var aes = AESContext.new()
aes.start(AESContext.MODE_CBC_DECRYPT, _encryptionKey.slice(0, 32), iv)
var decryptedBytes = aes.update(encryptedBytes)
aes.finish()
# 转换为字符串
return decryptedBytes.get_string_from_utf8()
## 生成密码哈希(用于网络传输)
## 注意:这是简单实现,实际应该使用更安全的算法(如 bcrypt, scrypt
func hashPassword(password: String, salt: String = "") -> String:
if password.is_empty():
return ""
var combined = password + salt
return combined.sha256_text()
## 验证密码哈希
func verifyPassword(password: String, hashedPassword: String, salt: String = "") -> bool:
return hashPassword(password, salt) == hashedPassword
## 生成随机 Salt
func generateSalt(length: int = 16) -> String:
var crypto = Crypto.new()
var randomBytes = crypto.generate_random_bytes(length)
return Marshalls.raw_to_base64(randomBytes)