如何将字典保存至SQL?Unity+PHP+Web SQL用户数据存储问询
解决方案:Unity+PHP+SQL 存储用户字典数据
针对你的需求,以下是完整的实现方案,包含数据库设计、Unity端数据处理、PHP端入库逻辑,以及防篡改的核心措施:
一、数据库表设计
根据stats的结构灵活性,提供两种可选方案:
1. 拆分字段方案(适合结构固定的stats)
如果stats的属性(如攻击力、防御力)是固定的,直接拆分为独立字段,便于快速查询和统计:
CREATE TABLE user_data ( user_id VARCHAR(50) PRIMARY KEY, -- 用户唯一标识(如UUID/账号ID) coins INT NOT NULL DEFAULT 0, attack INT NOT NULL DEFAULT 10, defense INT NOT NULL DEFAULT 10, -- 按需添加其他stats属性字段 updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
2. JSON序列化方案(适合灵活的stats)
如果stats属性可能动态增减,将其序列化为JSON字符串存储(MySQL 5.7+推荐使用JSON类型替代TEXT,支持JSON函数查询):
CREATE TABLE user_data ( user_id VARCHAR(50) PRIMARY KEY, coins INT NOT NULL DEFAULT 0, stats JSON NOT NULL, -- 存储stats字典的JSON格式数据 updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
二、Unity端:字典转JSON并发送请求
使用Newtonsoft.Json(Unity Package Manager可直接安装)处理字典序列化,搭配签名机制防止数据篡改:
using UnityEngine; using UnityEngine.Networking; using Newtonsoft.Json; using System.Collections; using System.Collections.Generic; public class UserDataManager : MonoBehaviour { private readonly string _phpApiUrl = "http://your-domain.com/save_user_data.php"; private readonly string _userId = "user_123456"; // 替换为实际用户唯一ID private readonly string _secretKey = "your_secure_secret_key"; // 和PHP端保持一致 public void SaveUserStats() { // 构建用户数据字典 var userData = new Dictionary<string, object> { {"user_id", _userId}, {"coins", 200}, {"stats", new Dictionary<string, int> { {"attack", 70}, {"defense", 50}, {"speed", 30} } } }; // 序列化为JSON字符串 string jsonData = JsonConvert.SerializeObject(userData); // 生成签名:JSON+密钥做MD5哈希(可替换为SHA256提升安全性) string signature = GenerateMd5Hash(jsonData + _secretKey); // 构建表单数据 var form = new WWWForm(); form.AddField("data", jsonData); form.AddField("signature", signature); // 发送POST请求 StartCoroutine(SendRequest(form)); } IEnumerator SendRequest(WWWForm form) { using (var request = UnityWebRequest.Post(_phpApiUrl, form)) { yield return request.SendWebRequest(); if (request.result != UnityWebRequest.Result.Success) { Debug.LogError($"请求失败: {request.error}"); } else { Debug.Log($"保存结果: {request.downloadHandler.text}"); } } } // MD5哈希生成工具 private string GenerateMd5Hash(string input) { using (var md5 = System.Security.Cryptography.MD5.Create()) { byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input); byte[] hashBytes = md5.ComputeHash(inputBytes); var sb = new System.Text.StringBuilder(); foreach (byte b in hashBytes) sb.Append(b.ToString("X2")); return sb.ToString(); } } }
三、PHP端:接收数据并写入SQL
使用PDO预处理语句防止SQL注入,同时验证签名确保数据未被篡改:
<?php // 数据库配置 $servername = "localhost"; $dbUser = "your_db_user"; $dbPass = "your_db_password"; $dbName = "your_database"; $secretKey = "your_secure_secret_key"; // 和Unity端一致 // 仅允许POST请求 if ($_SERVER['REQUEST_METHOD'] !== 'POST') { die("Invalid request method"); } // 接收并验证参数 $jsonData = $_POST['data'] ?? ''; $signature = $_POST['signature'] ?? ''; $expectedSignature = md5($jsonData . $secretKey); if ($signature !== $expectedSignature) { die("Error: Data tampered"); } // 解析JSON数据 $userData = json_decode($jsonData, true); if (!$userData || !isset($userData['user_id'], $userData['coins'], $userData['stats'])) { die("Error: Invalid data format"); } $userId = $userData['user_id']; $coins = (int)$userData['coins']; $statsJson = json_encode($userData['stats']); // 服务器端数据校验(防止恶意提交非法值) if ($coins < 0) { die("Error: Invalid coins value"); } // 连接数据库并执行入库操作 try { $conn = new PDO( "mysql:host=$servername;dbname=$dbName;charset=utf8mb4", $dbUser, $dbPass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] ); // 插入或更新用户数据(存在则更新,不存在则插入) $stmt = $conn->prepare(" INSERT INTO user_data (user_id, coins, stats) VALUES (:user_id, :coins, :stats) ON DUPLICATE KEY UPDATE coins = :coins, stats = :stats, updated_at = CURRENT_TIMESTAMP "); $stmt->bindParam(':user_id', $userId); $stmt->bindParam(':coins', $coins); $stmt->bindParam(':stats', $statsJson); $stmt->execute(); echo "Data saved successfully"; } catch(PDOException $e) { die("Database error: " . $e->getMessage()); } $conn = null; ?>
四、防篡改核心措施
- 请求签名验证:通过密钥对数据生成哈希,PHP端校验哈希值,确保传输过程中数据未被篡改。
- HTTPS传输:配置服务器启用HTTPS,避免数据被明文窃取或篡改。
- 服务器端校验:对coins、stats数值做合理性检查(如coins不能为负),拒绝非法数据。
- 禁用本地存储:严格遵循你的需求,所有数据仅在服务器端存储,客户端仅从服务器拉取最新数据。
内容的提问来源于stack exchange,提问作者Shadow341
相关产品推荐
相关产品推荐

