Pregunta

Estoy escribiendo una aplicación de servidor web en C # y usando la clase StreamReader para leer desde un NetworkStream subyacente:

 NetworkStream ns = new NetworkStream(clientSocket);
 StreamReader sr = new StreamReader(ns);
 String request = sr.ReadLine();

Este código es propenso a ataques DoS porque si el atacante nunca se desconecta nunca terminaremos de leer la línea. ¿Hay alguna forma de limitar el número de caracteres leídos por StreamReader.ReadLine () en .NET?

¿Fue útil?

Solución

Tendría que usar la sobrecarga Read (char [], int, int) (que limita la longitud) y realizar su propia detección de fin de línea; No debería ser demasiado complicado.

Para una versión ligeramente perezosa (que utiliza la versión de lectura de carácter único):

static IEnumerable<string> ReadLines(string path, int maxLineLength)
{
    StringBuilder currentLine = new StringBuilder(maxLineLength);
    using (var reader = File.OpenText(path))
    {
        int i;
        while((i = reader.Read()) > 0) {
            char c = (char) i;
            if(c == '\r' || c == '\n') {
                yield return currentLine.ToString();
                currentLine.Length = 0;
                continue;
            }
            currentLine.Append((char)c);
            if (currentLine.Length > maxLineLength)
            {
                throw new InvalidOperationException("Max length exceeded");
            }
        }
        if (currentLine.Length > 0)
        {
            yield return currentLine.ToString();
        }                
    }
}

Otros consejos

Es posible que necesite una de la sobrecarga StreamReader.Read :

Tomado de http://msdn.microsoft.com/en-us /library/9kstw824.aspx

    using (StreamReader sr = new StreamReader(path)) 
    {
        //This is an arbitrary size for this example.
        char[] c = null;

        while (sr.Peek() >= 0) 
        {
            c = new char[5];
            sr.Read(c, 0, c.Length);
            //The output will look odd, because
            //only five characters are read at a time.
            Console.WriteLine(c);
        }
    }

Enfóquese en la línea sr.Read (c, 0, c.Length) . Esto lee solo 5 caracteres de la secuencia y se coloca en la matriz c . Es posible que desee cambiar 5 al valor que desee.

Aquí está mi propia solución basada en la solución de Marc Gravell:

using System;
using System.IO;
using System.Text;

namespace MyProject
{
    class StreamReaderExt : StreamReader
    {

        public StreamReaderExt(Stream s, Encoding e) : base(s, e)
        {            
        }

        /// <summary>
        /// Reads a line of characters terminated by CR+LF from the current stream and returns the data as a string
        /// </summary>
        /// <param name="maxLineLength">Maximum allowed line length</param>
        /// <exception cref="System.IO.IOException" />
        /// <exception cref="System.InvalidOperationException">When string read by this method exceeds the maximum allowed line length</exception>
        /// <returns></returns>
        public string ReadLineCRLF(int maxLineLength)
        {
            StringBuilder currentLine = new StringBuilder(maxLineLength);

            int i;
            bool foundCR = false;
            bool readData = false;

            while ((i = Read()) > 0)
            {

                readData = true;

                char c = (char)i;

                if (foundCR)
                {
                    if (c == '\r')
                    {
                        // If CR was found before , and the next character is also CR,
                        // adding previously skipped CR to the result string
                        currentLine.Append('\r');
                        continue;
                    }
                    else if (c == '\n')
                    {
                        // LF found, finished reading the string
                        return currentLine.ToString();
                    }
                    else
                    {
                        // If CR was found before , but the next character is not LF,
                        // adding previously skipped CR to the result string
                        currentLine.Append('\r');
                        foundCR = false;
                    }
                }
                else // CR not found
                {
                    if (c == '\r')
                    {
                        foundCR = true;
                        continue;
                    }
                }

                currentLine.Append((char)c);
                if (currentLine.Length > maxLineLength)
                {
                    throw new InvalidOperationException("Max line length exceeded");
                }
            }

            if (foundCR)
            {
                // If CR was found before, and the end of the stream has been reached, appending the skipped CR character
                currentLine.Append('\r');
            }

            if (readData)
            {
                return currentLine.ToString();
            }

            // End of the stream reached
            return null;

        }
    }
}

Esta pieza de código se proporciona " TAL CUAL " sin GARANTÍA.

Siempre puedes usar " .Leer (...) " y MSDN recomienda hacerlo para una situación como la suya.

http://msdn.microsoft.com/en-us/library/system .io.streamreader.readline.aspx

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top