游戏数据安全性问题的思考
在之前的学习过程中,我了解到了Unity提供的一个存储方式——PlayerPrefs
这种存储方式在不同平台的数据存储位置放在文章末尾。
但是PlayerPrefs的这种存储方式,数据是很容易被找到并且篡改的,目前数据存储最安全的做法依然是
将数据发送到服务器,存储在服务器中。
对于游戏数据发送到服务器,最近也有一些新的想法,以下使用之前开发的一个Html5游戏代码举例:
1 //博客园目前好像没有TypeScript的编程语言选项,我就选了一个JS 2 class UserData{ 3 public id: number; // 数据库自增id 唯一id标识 4 public id_wx: string; // 微信id 5 public nickname: string; // 用户名 6 public icon: string; // 用户头像地址 7 public IP: string; // 用户ip地址 8 public passLayers: number; // 通过层数 9 public passLevels: number; // 当前关卡 10 public gameData: GameData; 11 } 12 13 class GameData{ 14 public noticeNum: number;//提示道具数量 15 public shuffleNum: number;//洗牌道具数量 16 public hpUpNum: number;//加血道具数量 17 }
这样将服务器不需要处理的数据放入一个GameData中,由客户端进行解析和计算,服务端就不需要再增加额外的字段,如果有新的
需要提交的数据,我们只需要在客户端的GameData中添加即可,这些数据在服务端保存,然后原封不动的传回客户端,由客户端解析
可以减小服务器压力。
然而,对于很多个人开发者来说,或者对于纯单机游戏来说,不需要服务器的时候,我们也可以使用PlayerPrefs进行数据存储。
如上文的GameData一样,我们可以将数据在客户端进行解析,也就是说,我们使用PlayerPrefs存储一个加密后的数据,然后在
客户端进行读取解析,即可增加一定的数据安全性。
我们可以使用System.Security.Cryptography,或者也可以使用外部库:如 SecurePrefs
示例:
using System.Security.Cryptography; using System.Text; public static class SecurePlayerPrefs { private static string encryptionKey = "SecretKey"; public static void SetEncryptedString(string key, string value) { string encryptedValue = Encrypt(value, encryptionKey); PlayerPrefs.SetString(key, encryptedValue); } public static string GetEncryptedString(string key) { string encryptedValue = PlayerPrefs.GetString(key); return Decrypt(encryptedValue, encryptionKey); } private static string Encrypt(string text, string key) { // 加密逻辑(使用AES等算法) return Convert.ToBase64String(Encoding.UTF8.GetBytes(text + key)); } private static string Decrypt(string encryptedText, string key) { // 解密逻辑 var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(encryptedText)); return decoded.Replace(key, ""); } }
还可以增加一个校验机制(使用MD5或者SHA256):
string data = "playerScore=100"; string hash = GenerateHash(data); // 使用 SHA256 生成哈希值 PlayerPrefs.SetString("data", data); PlayerPrefs.SetString("hash", hash); string savedData = PlayerPrefs.GetString("data"); string savedHash = PlayerPrefs.GetString("hash"); if (GenerateHash(savedData) == savedHash) { Debug.Log("数据未被篡改"); } else { Debug.Log("数据已被修改!"); }
但是这样做有一个很显著的缺点,就是被逆向破解之后,数据依然可以被篡改。(毕竟数据全部是在客户端进行解析的,但是这种情况,游戏都被逆向了,对于单机游戏来说
数据什么的,反倒是小事情了吧。。。)
PlayerPrefs在各个平台的存储位置:
1.Windows上的存储位置:
在Windows系统中,PlayerPrefs的数据存储在注册表中。具体路径为:
公司名和项目名可以在Unity的Edit -> Project Settings -> Player中查看和设置
2.macOS上的存储位置
在macOS系统中,PlayerPrefs的数据存储在以下路径:
Unity在编辑器和独立播放器中使用相同的.plist文件
3.Linux上的存储位置
在Linux系统中,PlayerPrefs的数据存储在以下路径:
4.Android上的存储位置
在Android系统中,PlayerPrefs的数据存储在以下路径:
Unity将PlayerPrefs数据存储在设备的SharedPreferences中
5.WebGL上的存储位置
在WebGL平台上,Unity使用浏览器的IndexedDB API存储PlayerPrefs数据