Unity3d实战之Unity3d网络游戏实战篇(7):数据管理类DataMgr
学习书籍《Unity3d网络游戏实战》 罗培羽著 机械工业出版社
本文是作者在学习过程中遇到的认为值得记录的点,因此引用的代码等资源基本出资罗培羽老师的书籍,如有侵权请联系,必删。
DataMgr是封装数据库操作的类,它实现了用户名密码验证、注册、创建角色、获取角色数据、保存角色数据。
Register:向user表插入user_name 和 password;
CreatePlayer:创建默认PlayerData并存入player中;
CheckPassWord:检查user_name 和 password对能否在user表中找到对应数据;
GetPlayerData:根据user_name在player找出对应的data;
SavePlayer:根据user_name更新player中的data;
辅助用的方法:
private bool IsSafeStr(string str);
通常,我们注册一个账号、创建一个新角色并给他输入昵称时会看到有一些字符是不允许输入的,这是为了防止sql注入,所谓sql注入就是用户在用户名栏或者密码栏中恶意输入sql命令,由于程序是通过用户输入来进行数据库查询的,因此很有可能会发生数据库被破坏的情况。例如:
用户注册了用户名为”xiaoming; delete * from player;”的名字,该字符串传到程序中会执行如下数据库操作命令:
select * from player where id=xiaoming; delete * from player;
瞬间爆炸!所以一定要对用户的输入进行特殊字符的排除!
/// <summary>
/// Check the string , if it has illegal characters.
/// </summary>
/// <returns><c>true</c> if this instance is safe string the specified str; otherwise, <c>false</c>.</returns>
/// <param name="str">string</param>
bool IsSafeStr(string str)
{
return !Regex.IsMatch (str, @"[-|;|,|\/|\(|\)|\[|\]|\}|\{|%|@|\*|!|\']");
}
private bool canRegister(string id, string pw);
用于检测用户输入的用户名和密码是否已注册,实现方法如下:
/// <summary>
/// Check the password.
/// </summary>
/// <returns><c>true</c>, if password was checked, <c>false</c> otherwise.</returns>
/// <param name="id">user_name</param>
/// <param name="pw">password</param>
public bool CheckPassword(string id, string pw)
{
if (!IsSafeStr (id) || !IsSafeStr (pw)) {
Console.WriteLine ("[DataMgr.CheckPassword] Illegal characters.");
return false;
}
string formatStr = "select * from user where id='{0}' and pw='{1}';";
string cmdStr = string.Format (formatStr, id, pw);
MySqlCommand cmd = new MySqlCommand (cmdStr, sqlConn);
try {
MySqlDataReader dataReader = cmd.ExecuteReader();
bool hasRow = dataReader.HasRows;
dataReader.Close();
return hasRow;
} catch (Exception ex) {
Console.WriteLine ("[DataMgr.CheckPassword] Read data fail. " + ex.Message);
return false;
}
}
余下的Register、CreatePlayer等方法的实现都是使用不同的SQL语句来实现查询、插入、读取数据等操作。编写代码的过程中要注意代码风格的一致性以及异常捕获后输出的提示信息要清晰明了,防止后面Debug的时候找不着北…血与泪的教训。
给出两个Sample:
/// <summary>
/// Check the password.
/// </summary>
/// <returns><c>true</c>, if password was checked, <c>false</c> otherwise.</returns>
/// <param name="id">user_name</param>
/// <param name="pw">password</param>
public bool CheckPassword(string id, string pw)
{
if (!IsSafeStr (id) || !IsSafeStr (pw)) {
Console.WriteLine ("[DataMgr.CheckPassword] Illegal characters.");
return false;
}
string formatStr = "select * from user where id='{0}' and pw='{1}';";
string cmdStr = string.Format (formatStr, id, pw);
MySqlCommand cmd = new MySqlCommand (cmdStr, sqlConn);
try {
MySqlDataReader dataReader = cmd.ExecuteReader();
bool hasRow = dataReader.HasRows;
dataReader.Close();
return hasRow;
} catch (Exception ex) {
Console.WriteLine ("[DataMgr.CheckPassword] Read data fail. " + ex.Message);
return false;
}
}
/// <summary>
/// Create a playerData for player whose id is args' id.
/// </summary>
/// <returns><c>true</c>create player success, <c>false</c>can't create player</returns>
/// <param name="id">user_name</param>
public bool CreatePlayer(string id)
{
if (!IsSafeStr (id)) {
Console.WriteLine ("[DataMgr.CreatePlayer] Illegal characters.");
return false;
}
PlayerData playerData = new PlayerData ();
MemoryStream stream = new MemoryStream ();
BinaryFormatter formatter = new BinaryFormatter ();
try {
formatter.Serialize(stream, playerData);
} catch (Exception ex) {
Console.WriteLine ("[DataMgr.CreatePlayer] Serialize data fail. " + ex.Message);
return false;
}
byte[] dataBytes = stream.ToArray ();
string formatStr = "insert into player set id='{0}', data=@data;";
string cmdStr = string.Format (formatStr, id);
MySqlCommand cmd = new MySqlCommand (cmdStr, sqlConn);
cmd.Parameters.Add ("@data", MySqlDbType.Blob);
cmd.Parameters [0].Value = dataBytes;
try {
cmd.ExecuteNonQuery();
return true;
} catch (Exception ex) {
Console.WriteLine ("[DataMgr.CreatePlayer] Execute command fail. " + ex.Message);
return false;
}
}