简体   繁体   English

414-请求的uri太长-网址长度为70个字符

[英]414 - The requested uri is too long - the url is 70 characters long

I tried to make a authentication with C#. 我尝试使用C#进行身份验证。

It sends an HTTP GET request on login attempt, it looks like: 它在登录尝试时发送HTTP GET请求,如下所示:

https://goldenarmy.eu/studios/id/cman/clogin.php?name=abc&password=abc https://goldenarmy.eu/studios/id/cman/clogin.php?name=abc&password=abc

And this is only 70 characters. 而且只有70个字符。 But I get a "Request-URI too long" error. 但是我收到“请求URI太长”错误。

错误

Edit: It seems like the simulating works, but not when sended over TcpClient?! 编辑:似乎模拟工作,但不是通过TcpClient发送时!

图片

Clientmanager: 客户经理:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;


public class ClientManager
{
    private static TcpListener listener;

    public static void Main()
    {

        ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

        listener = new TcpListener(IPAddress.Any, 10250);
        listener.Start();
        Console.WriteLine("*** ClientManager started ***");
        Console.WriteLine("Listening to port 10250, make sure not used.");
        StartAccept();

        while (true)
        {
            System.Threading.Thread.Sleep(1000);
            string cmd = Console.ReadLine();

            if (cmd.Equals("exit"))
            {
                Console.WriteLine("*** Stopping cman... ***");
                Environment.Exit(0);
            }

            if (cmd.StartsWith("auth"))
            {

                Console.WriteLine("[" + "simulate" + "] Using auth cred to authenticate.");
                char c = '|';
                string[] args = cmd.Split(c);

                if (!(args.Length > 2))
                {
                    Console.WriteLine("INVALID_DATA_GIVEN");
                }
                string username = args[1];
                string password = args[2];

                Console.WriteLine("[" + "simulate" + "] Using credentials: " + username + " and " + password);

                string response = GetAsync(("https://goldenarmy.eu/studios/id/cman/clogin.php?name=" + username + "&password=" + password + "&test=1"));
                Console.WriteLine("https://goldenarmy.eu/studios/id/cman/clogin.php?name=" + username + "&password=" + password);
                Console.WriteLine(response);

                if (response.Equals("ERROR_FAILED_CONNECTION"))
                {
                    Console.WriteLine("ERROR_SERVERERROR");
                }
                else if (response.Equals("INVALID_USERNAME"))
                {
                    Console.WriteLine("INVALID_DATA_GIVEN");
                }
                else if (response.Equals("INVALID_PASSWORD"))
                {
                    Console.WriteLine("INVALID_DATA_GIVEN");
                }
                else if (response.Equals("INVALID_CRED"))
                {
                    Console.WriteLine("ERROR_AUTH_INVALID_CRED");
                }
                else if (response.Equals("IS_BANNED"))
                {
                    Console.WriteLine("ERROR_AUTH_BANNED");
                }
                else
                {
                    Console.WriteLine("[" + "simulate" + "] LOGIN OK | RESPONSE: " + response);
                }
            }
        }

    }
    private static void StartAccept()
    {
        listener.BeginAcceptSocket(HandleAsyncConnection, listener);
    }
    private static void HandleAsyncConnection(IAsyncResult res)
    {
        StartAccept();
        TcpClient client = listener.EndAcceptTcpClient(res);
        string clientSession = "NULL";
        string ip = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();

        Console.WriteLine("[" + ip + "] Incoming connection.");

        while (true)
        {
            try
            {
                System.Threading.Thread.Sleep(250);
                Console.WriteLine("Trying to read data from " + ip);
                NetworkStream stream = null;
                Byte[] data = new Byte[8192];
                String responseData = String.Empty;
                Int32 bytes = 0;

                stream = client.GetStream();
                bytes = stream.Read(data, 0, data.Length);
                Console.WriteLine("Bytes: " + bytes + " Data: " + System.Text.Encoding.ASCII.GetString(data));
                responseData = System.Text.Encoding.ASCII.GetString(data);


                Console.WriteLine("[" + ip + "] " + responseData);

                if (responseData.StartsWith("close"))
                {
                    Console.WriteLine("[" + ip + "] Connection closed.");
                    break;
                }else if (responseData.StartsWith("useauthtoken"))
                {
                    Console.WriteLine("[" + ip + "] Using auth token to authenticate.");
                    char c = '|';
                    string[] args = responseData.Split(c);

                    if (!(args.Length > 1))
                    {
                        SendMessage(stream, "INVALID_DATA_GIVEN");
                    }

                    string response = GetAsync("http://goldenarmy.eu/studios/id/cman/cauthtokencheck.php?auth=" + args[1]);

                    if (response.Equals("yes"))
                    {
                        clientSession = args[1];
                        SendMessage(stream, "OK");
                    }
                    else
                    {
                        SendMessage(stream, "ERROR_AUTH_INVALID");
                    }
                }
                else if (responseData.StartsWith("auth"))
                {

                    Console.WriteLine("[" + ip + "] Using auth cred to authenticate.");
                    char c = '|';
                    string[] args = responseData.Split(c);
                    Console.WriteLine("Data splitted");

                    if (!(args.Length > 2))
                    {
                        SendMessage(stream, "INVALID_DATA_GIVEN");
                    }
                    string username = args[1];
                    string password = args[2];

                    Console.WriteLine("[" + ip + "] Using credentials: " + username + " and " + password);

                    Console.WriteLine("Logging in...");
                    string response = GetAsync(("https://goldenarmy.eu/studios/id/cman/clogin.php?name=" + username + "&password=" + password + ""));
                    Console.WriteLine("Login attempt completed, with " + response);

                    if (response.Equals("ERROR_FAILED_CONNECTION"))
                    {
                        SendMessage(stream, "ERROR_SERVERERROR");
                    }
                    else if (response.Equals("INVALID_USERNAME"))
                    {
                        SendMessage(stream, "INVALID_DATA_GIVEN");
                    }
                    else if (response.Equals("INVALID_PASSWORD"))
                    {
                        SendMessage(stream, "INVALID_DATA_GIVEN");
                    }
                    else if (response.Equals("INVALID_CRED"))
                    {
                        SendMessage(stream, "ERROR_AUTH_INVALID_CRED");
                    }
                    else if (response.Equals("IS_BANNED"))
                    {
                        SendMessage(stream, "ERROR_AUTH_BANNED");
                    }
                    else
                    {
                        Console.WriteLine("[" + ip + "] LOGIN OK | RESPONSE: " + response);
                        if (response == null) response = "Response was null?";
                        SendMessage(stream, response);
                        Console.WriteLine("Sended message...");
                        clientSession = response;
                    }
                }

                if ((!responseData.StartsWith("auth") || !responseData.StartsWith("useauthtoken") || !responseData.StartsWith("close")) && clientSession.Equals("NULL"))
                {
                    SendMessage(stream, "ERROR_AUTH_MISSING");
                }

                if (responseData.Equals("endGame"))
                {
                    char c = '|';
                    string[] args = responseData.Split(c);

                    if (!(args.Length > 3))
                    {
                        SendMessage(stream, "INVALID_DATA_GIVEN");
                    }

                    string won = args[0];
                    string kills = args[1];
                    string singleplayer = args[2];

                    string response = GetAsync("https://goldenarmy.eu/studios/id/cman/cgameend.php?session=" + client + "&won=" + won + "&kills=" + kills + "&singleplayer=" + singleplayer);

                    if (response.Equals("ERROR_FAILED_CONNECTION"))
                    {
                        SendMessage(stream, "ERROR_SERVERERROR");
                    }
                    else if (response.Equals("SESSION_INVALID"))
                    {
                        SendMessage(stream, "ERROR_AUTH_MISSING");
                    }
                    else if (response.Equals("SUCCESS"))
                    {
                        SendMessage(stream, "SUCCESS");
                    }
                }


            }
            catch (Exception e)
            {
                Console.WriteLine("[" + ip + "] Connection closed: " + e.Message);
                break;
            }
        }
    }

    public static string GetAsync(string uri, Action<WebHeaderCollection> headers = null)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
        //request.Headers.Set(HttpRequestHeader.ContentLocation, uri);
        //request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

        Console.WriteLine(request.RequestUri);
        using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
        using (Stream stream = response.GetResponseStream())
        using (StreamReader reader = new StreamReader(stream))
        {
            return reader.ReadToEnd();
        }
    }

    public static void SendMessage(NetworkStream stream, string msg)
    {
        Byte[] sendBytes = Encoding.ASCII.GetBytes(msg);
        stream.Write(sendBytes, 0, sendBytes.Length);
    }

    /*public static string login(string username, string password)
    {
        Console.WriteLine("https://goldenarmy.eu/studios/id/cman/clogin.php?name=" + username + "&password=" + password);
        string response = GetAsync(("https://goldenarmy.eu/studios/id/cman/clogin.php?name=" + username + "&password=" + password));

        Console.WriteLine(response);

        return response;
    }*/

    public static bool MyRemoteCertificateValidationCallback(System.Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        bool isOk = true;

        return isOk;
    }
}

clogin.php: clogin.php:

    <?php
$conn = new mysqli("localhost", "root", "not-the-real-password", "topdown");

if ($conn->connect_error) {
    die("ERROR_FAILED_CONNECTION");
} 
$name = $_GET["name"];
$password = $_GET["password"];

function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

function endsWith($haystack, $needle)
{
    $length = strlen($needle);
    if ($length == 0) {
        return true;
    }

    return (substr($haystack, -$length) === $needle);
}

    $sql = "SELECT `password`,`banned` FROM `accounts` WHERE `name`='".$name."';";
    $result = $conn->query($sql);

    if ($result->num_rows < 1) { 
        die("INVALID_CRED");
        die();
    }

    $found = "";
    $banned = false;

    while($row = $result->fetch_assoc()) {
        $found = $row["password"];
        $banned = $row["banned"];
    }

    if($found == $password){
        if($banned==1){
            die("IS_BANNED");
        }

        $session = generateRandomString(16);
        $sql = "UPDATE `accounts` SET `clientsession`='".$session."' WHERE `name`='".$name."'";

        if ($conn->query($sql) === TRUE) {
            die($session);
        }else{
            die("ERROR_FAILED_CONNECTION");
        }
    }else{
        die("INVALID_CRED");
    }
?>

That message is coming from the server, not the client. 该消息来自服务器,而不是客户端。 See this answer for possible solutions: How do I resolve a HTTP 414 "Request URI too long" error? 请参阅此答案以获取可能的解决方案: 如何解决HTTP 414“请求URI太长”错误?

Your simulation does not reflect what you send in in the non-simulated case to the server and that's why you cannot reproduce the error in the simulation. 模拟不能反映您在非模拟情况下向服务器发送的内容,这就是为什么您无法在模拟中重现错误。

In the simulated case you read a line and the length of the string cmd is the line length. 在模拟的情况下,您读取一条线,而字符串cmd的长度就是该线的长度。 In the non-simulated case you instead read into a buffer data which has a size of 8192 bytes. 在非模拟情况下,您改为读取8192字节大小的缓冲区data This means that if you read the response of auth|abc|abc the contents of data will be auth|abc|abc\\0\\0\\0\\0.... , ie the content send by the server and then 8180 (8192-12) characters \\0 (ie \\x00 , \\000 or however this can be written in C#). 这意味着,如果您读取auth|abc|abc的响应,则data内容将为auth|abc|abc\\0\\0\\0\\0.... ,即服务器发送的内容,然后为8180(8192 -12)字符\\0 (即\\x00\\000 ,但是可以用C#编写)。

After your responseData.Split the password (ie args[2] ) will therefore not be abc as you expected but abc\\0\\0\\0\\0.... . 因此,在您的responseData.Split ,密码(即args[2] )将不是您期望的abc ,而是abc\\0\\0\\0\\0.... This again means that the URL which should be https://....?user=abc&pass=abc is in reality https://....?user=abc&pass=abc\\0\\0\\0.... . 这再次意味着应该为https://....?user=abc&pass=abc的URL实际上是https://....?user=abc&pass=abc\\0\\0\\0.... The \\0 needs to be encoded with URL encoding as %00 which results in https://....?user=abc&pass=abc%00%00%00.... \\0必须使用%00 URL编码进行编码,这会导致https://....?user=abc&pass=abc%00%00%00....

And already all these 8180 %00 will result in 24540 characters in the URL alone, which explains why the server complains about the URL being too large. 并且所有这些8180 %00仅在URL中就会产生24540个字符,这解释了为什么服务器抱怨URL太大。 A look into the servers access log or error log will probably show this kind of problem too. 查看服务器访问日志或错误日志也可能会显示此类问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM