You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将字典保存至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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:50:33