服务器不从数据库中获取信息并将其传递给客户端

时间:2016-01-27 11:49:00

标签: c# actionscript-3 mmo

我试图让我的服务器从登录用户(web)获取sso并将其传递给AS3客户端。

如果我在客户端(下图)中设置了特定的SSO,则服务器会从数据库中选择用户。

目前我收到错误消息:错误1:您的SSO票证无效。请重新登录然后重新加载。

var flashvars = {
    sso: "<?php echo $self['sso_ticket']; ?>"
};

我在用户登录网站后获取ssoTicket值并使用SWF启动页面,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ParticleFramework.Communication;
using ParticleFramework.Storage;
using ParticleFramework;
using MySql.Data.MySqlClient;
using ArchiCruise.Rooms;

namespace ArchiCruise.Users
{
    static class Handler
    {

        public static List<UserObject> clientObjects = new List<UserObject>();

        public static void login(string ssoTicket, TcpClient client)
        {
            if (ssoTicket == "")
            {
                client.Disconnect();
                return;
            }
            Log.Info("Client " + client.index + " logging in with SSO: " + ssoTicket);

            if (DBManager.database.getString("SELECT COUNT(*) FROM users` WHERE sso_ticket like '%" + ssoTicket.Trim() + "%'") != "0")
            {
                DBManager.database.closeClient();
                //build the user object
                UserObject userObject = newObject(ssoTicket, client);

                foreach (UserObject user in clientObjects)
                {
                    if (user.username == userObject.username)
                    {
                        user.tcpClient.Disconnect();
                    }
                }

                if (clientObjects.Count <= client.index || clientObjects[client.index] == null)
                {
                    client.userObject = userObject;
                    clientObjects.Add(userObject);
                }
                else
                {
                    client.userObject = userObject;
                    clientObjects[client.index] = userObject;
                }
                client.sendData("LO" + (char)13 + userObject.ToPrivate());
                DBManager.database.closeClient();
            }
            else
            {
                DBManager.database.closeClient();
                client.sendData("ER 1: You have an invalid SSO ticket. Please re-login and then reload.");
            }
        }

        public static void toAll(string Data)
        {
            foreach (UserObject user in clientObjects)
            {
                user.tcpClient.sendData(Data);
            }
        }

        public static void toAll(string Data, Boolean disconnect)
        {
            foreach (UserObject user in clientObjects)
            {
                user.tcpClient.sendData(Data);
                if (disconnect) user.tcpClient.Disconnect();
            }
        }

        public static void toUser(string Data, string uname)
        {
            foreach (UserObject user in clientObjects)
            {
                if (user.username.ToLower() == uname.ToLower())
                {
                    user.tcpClient.sendData(Data);
                }
            }
        }

        public static void toUser(string Data, string uname, Boolean disconnect)
        {
            foreach (UserObject user in clientObjects)
            {
                if (user.username.ToLower() == uname.ToLower())
                {
                    user.tcpClient.sendData(Data);
                    if (disconnect)
                    {
                        user.tcpClient.Disconnect();
                    }
                }
            }
        }

        public static void toRoom(int roomID, TcpClient client)
        {
            if (clientObjects.Count >= client.index && client.userObject.roomID != roomID)
            {
                Log.Info("Client " + client.index + " going to public room " + roomID);

                if (DBManager.database.getString("SELECT COUNT(*) FROM `public` WHERE `id` = '" + roomID + "';") != "0")
                {
                    DBManager.database.closeClient();

                    //kick plz
                    if (client.userObject.roomID > 0)
                    {
                        client.userObject.toRoom("KO " + client.userObject.username);
                    }

                    //update user object
                    MySqlDataReader mysqlRead = DBManager.database.getCommand("SELECT * FROM `public` WHERE `id` = '" + roomID + "' LIMIT 1").ExecuteReader();
                    mysqlRead.Read();

                    client.userObject.toRoom(roomID, Convert.ToInt32(mysqlRead["startpos"].ToString().Split(',')[0]), Convert.ToInt32(mysqlRead["startpos"].ToString().Split(',')[1]));

                    client.sendData("RO" + mysqlRead["layout"].ToString() + (char)13 + mysqlRead["name"].ToString() + (char)13 + (char)12 + mysqlRead["heightmap"].ToString() + (char)12 + mysqlRead["warps"].ToString());

                    DBManager.database.closeClient();
                }
                else
                {
                    DBManager.database.closeClient();
                    client.sendData("ER 1: You have an invalid SSO ticket. Please re-login and then reload.");
                }
            }
        }

        public static void moveUser(TcpClient client, int _x, int _y)
        {
            client.userObject.x = _x;
            client.userObject.y = _y;
            client.userObject.toRoom("MV " + client.userObject.username + " " + _x + " " + _y);
        }

        public static void sendNavigationList(TcpClient client, int pub)
        {
            string nList = "NV" + (char)13;
            MySqlDataReader mysqlRead = DBManager.database.getCommand("SELECT * FROM `public` WHERE `show` = 'yes' AND `public` = '" + pub + "'").ExecuteReader();

            while (mysqlRead.Read())
            {
                nList += mysqlRead["id"].ToString() + (char)14 + mysqlRead["name"].ToString() + (char)13;
            }

            DBManager.database.closeClient();

            client.sendData(nList);
        }

        public static void sendUserList(TcpClient client)
        {
            string userList = "UE" + (char)13;

            client.userObject.toRoom("UL" + (char)13 + client.userObject.ToString());

            foreach (UserObject user in clientObjects)
            {
                if (user.roomID == client.userObject.roomID && user.tcpClient != null)
                {
                    if (user.username != client.userObject.username && !userList.Contains(user.username + "@"))
                    {
                        userList += user.ToString();
                    }
                }
            }

            client.sendData(userList);

            //Send room object
            client.sendData("RB" + (char)13 + RoomObjects.buildObjects(client.userObject.roomID));
        }

        public static UserObject newObject(string ssoTicket, TcpClient tClient)
        {
            MySqlDataReader mysqlRead = DBManager.database.getCommand("SELECT * FROM `users` WHERE `sso_ticket` = '" + ssoTicket + "' LIMIT 1").ExecuteReader();
            mysqlRead.Read();

            return new UserObject(mysqlRead["name"].ToString(), Convert.ToInt32(mysqlRead["rank"]), Convert.ToInt32(mysqlRead["credits"]), tClient);
        }

    }
}

来自服务器的处理程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ParticleFramework.Storage
{
    static class DBManager
    {
        public static Database database;

        public static Boolean Initialize(string type, string user, string pass, string host, string dbname)
        {
            switch (type)
            {
                case "sql":
                    database = new MySQL();
                    break;

                default:
                    Log.Error("Invalid database type! (" + type + ")");
                    break;
            }

            if (database != null)
            {
                return database.connect(user, pass, dbname, host);
            }
            else
            {
                return false;
            }
        }
    }
}

请求的DBManager类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;

namespace ParticleFramework.Storage
{
    class MySQL : Database
    {
        private MySqlConnection connection;

        public Boolean connect(string username, string password, string database, string host)
        {
            try
            {
                connection = new MySqlConnection(buildConnectionString(username, password, database, host));
                Console.WriteLine("Database connected.  Running test query...");
                getString("SHOW TABLES FROM `" + database + "`");
                Log.Info("Test query succeeded.  Database initialized.");
                closeClient();

                return true;
            }
            catch (Exception e)
            {
                Log.Error("MySQL Connect: " + e.Message);
                return false;
            }
        }

        public string getString(string query)
        {
            try
            {
                string resultStr = getCommand(query).ExecuteScalar().ToString();
                closeClient();

                return resultStr;
            }
            catch (Exception e)
            {
                Log.Error("MySQL getString: " + e.Message);
                return "";
            }
        }

        public MySqlCommand getCommand(string query)
        {
            try
            {
                if (connection.State != System.Data.ConnectionState.Closed)
                {
                    connection.Close();
                }

                MySqlCommand command = newCommand();
                command.CommandText = query;
                connection.Open();
                return command;
            }
            catch (Exception e)
            {
                Log.Error("MySQL getCommand: " + e.Message);
                return null;
            }
        }

        public void noCommand(string query)
        {
            try
            {
                if (connection.State != System.Data.ConnectionState.Closed)
                {
                    connection.Close();
                }

                MySqlCommand command = newCommand();
                command.CommandText = query;
                connection.Open();
                command.ExecuteNonQuery();
                connection.Close();
            }
            catch (Exception e)
            {
                Log.Error("MySQL noCommand: " + e.Message);
            }
        }

        public void closeClient()
        {
            try
            {
                if (connection.State == System.Data.ConnectionState.Open)
                {
                    connection.Close();
                }
            }
            catch (Exception e)
            {
                Log.Error("MySQL closeClient: " + e.Message);
            }
        }

        public MySqlCommand newCommand()
        {
            try
            {
                return connection.CreateCommand();
            }
            catch (Exception e)
            {
                Log.Error("MySQL newCommand: " + e.Message);
                return null;
            }
        }

        public string buildConnectionString(string username, string password, string database, string host)
        {
            return "Database=" + database + ";Data Source=" + host + ";User Id=" + username + ";Password=" + password;
        }
    }
}

MySQL类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;

namespace ParticleFramework.Storage
{
    interface Database
    {
        Boolean connect(string username, string password, string database, string host);
        MySqlCommand newCommand();
        MySqlCommand getCommand(string query);

        string buildConnectionString(string username, string password, string database, string host);
        string getString(string query);
        void noCommand(string query);

        void closeClient();
    }
}

数据库类

>[1/1/0001 00:00:00] 127.0.0.1connected.  Full 127.0.0.1:56765
>[1/1/0001 00:00:00] Got LO null  from client 0
>[1/1/0001 00:00:00] Client 0 logging in with SSO: null
>[ERROR]Packet handler: MySql.Data.MySqlClient.MySqlException (0x80004005): Invalid attempt to access a field before calling Read()
>   at MySql.Data.MySqlClient.ResultSet.get_Item(Int32 index)
>   at MySql.Data.MySqlClient.MySqlDataReader.GetFieldValue(Int32 index, Boolean checkNull)
>   at MySql.Data.MySqlClient.MySqlDataReader.GetValue(Int32 i)
>   at MySql.Data.MySqlClient.MySqlDataReader.get_Item(Int32 i)
>   at MySql.Data.MySqlClient.MySqlDataReader.get_Item(String name)
>   at ArchiCruise.Users.Handler.newObject(String ssoTicket, TcpClient tClient) in C:\Users\Daniel\Desktop\AC\Particle Server\Particle Server\ArchiCruise\Users\Handler.cs:line 188
>   at ArchiCruise.Users.Handler.login(String ssoTicket, TcpClient client) in C:\Users\Daniel\Desktop\AC\Particle Server\Particle Server\ArchiCruise\Users\Handler.cs:line 31
>   at ArchiCruise.ArchiCruisePackets.handle(String packet, TcpClient client) in C:\Users\Daniel\Desktop\AC\Particle Server\Particle Server\ArchiCruise\ArchiCruisePackets.cs:line 23
>[1/1/0001 00:00:00] Client0 disconnected and removed.

SSO更改后的日志信息

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace ParticleFramework.Communication
{
    class TcpClient
    {
        #region Required Variables
        public Socket socket;
        public int index;
        private byte[] dataBuffer = new byte[0x400];
        private AsyncCallback ReceiveCallback;
        private AsyncCallback SendCallback;
        #endregion

        #region ArchiCruise Vars
        public ArchiCruise.Users.UserObject userObject;
        public string ip;
        #endregion

        public TcpClient(Socket sock, int num)
        {
            index = num;
            socket = sock;

            ip = socket.RemoteEndPoint.ToString().Split(new char[] { ':' })[0];

            ReceiveCallback = new AsyncCallback(this.ReceivedData);
            SendCallback = new AsyncCallback(this.sentData);

            this.WaitForData();
        }

        public void Disconnect()
        {
            if (socket.Connected)
            {
                socket.Close();
                if (userObject != null) userObject.remove();
                Particle.Server.removeClient(this);
                Log.Info("Client" + this.index + " disconnected and removed.");
                Console.WriteLine("Client" + this.index + " disconnected.");
            }
        }

        private void ReceivedData(IAsyncResult iAr)
        {
            try
            {
                int count = 0;

                try
                {
                    count = socket.EndReceive(iAr);
                }
                catch
                {
                    Disconnect();
                }

                StringBuilder builder = new StringBuilder();
                builder.Append(System.Text.Encoding.Default.GetString(this.dataBuffer, 0, count));
                string str = System.Text.Encoding.Default.GetString(this.dataBuffer, 0, count);

                if (str.Contains("<policy-file-requet/>"))
                {
                    Log.Info("Sending policy file to client" + this.index);
                    rawSend("<?xml version\"1.0\"?><cross-domain-policy><allow-access-from-domain=\"*\" to-ports=\"*\" /><cross-domain-policy>" + Convert.ToChar(0));
                }
                else if (!(str.ToString() == ""))
                {
                    string packet = str.Substring(0, str.Length - 1);
                    //packet = ArchiCruise.Security.Encryption.decrypt(packet);
                    Log.Info("Got " + str + " from client " + this.index);

                    Particle.packetClass.handle(packet, this);
                }
                else
                {
                    Disconnect();
                }
            }
            catch (Exception exception)
            {
                Log.Info("Data recieve error: " + exception.ToString() + " " + exception.Source);
                Disconnect();
            }
            finally
            {
                this.WaitForData();
            }
        }

        private void WaitForData()
        {
            try
            {
                socket.BeginReceive(this.dataBuffer, 0, this.dataBuffer.Length, SocketFlags.None, this.ReceiveCallback, socket);
            }
            catch
            {
                Disconnect();
            }
        }

        public void sendData(string Data)
        {
            Data += (char)1;
            rawSend(Data);
        }

        internal void rawSend(string Data)
        {
            try
            {
                Data += "\0";
                byte[] bytes = System.Text.Encoding.Default.GetBytes(Data);

                socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(this.sentData), null);
                Log.Info("Sent " + Data + " to client " + this.index);
            }
            catch
            {
                Disconnect();
            }
        }

        private void sentData(IAsyncResult iAr)
        {
            try
            {
                socket.EndSend(iAr);
            }
            catch
            {
                Disconnect();
            }
        }
    }
}

Tcpclient类

error(Object message, Throwable t)

2 个答案:

答案 0 :(得分:1)

我建议你使用mysql ORM。您的代码非常容易出错,并且对SQL注入攻击非常脆弱。

但是,从错误日志中可以看出,您没有检查sql查询是否正确执行并且其中包含值。您可以使用if检查轻松完成此操作:

public static UserObject newObject(string ssoTicket, TcpClient tClient)
{
    string sqlQuery = "SELECT * FROM `users` WHERE `sso_ticket` = '" + ssoTicket + "' LIMIT 1";
    MySqlDataReader mysqlRead = DBManager.database.getCommand( sqlQuery ).ExecuteReader();
    if (mysqlRead.Read()) // read the query and check if we got any data
    {
        return new UserObject(mysqlRead["name"].ToString(), Convert.ToInt32(mysqlRead["rank"]), Convert.ToInt32(mysqlRead["credits"]), tClient);  
    }
    else
    {
       Log.Error("sqlQuery failed : " + sqlQuery );
       return null; //you should check the returned value if its null or not to prevent further problems.
    }                           
}

使用此代码,您可以检查您的查询是否错误。我建议你逐步调试,看看变量中是否有正确的值。检查Microsoft的Debugging in Visual Studio以获取有关调试的更多信息。

答案 1 :(得分:0)

我认为问题是您正在使用ExecuteScalar来获取结果集。 您应该使用MySqlCommand.ExecuteReader方法

https://dev.mysql.com/doc/connector-net/en/connector-net-ref-mysqlclient-mysqlcommandmembers.html#connector-net-ref-mysqlclient-mysqlcommand-executereader-overload-1