[英]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.