【问题标题】:Safely reading http request headers in java在java中安全读取http请求头
【发布时间】:2014-10-23 17:47:30
【问题描述】:

我正在用 java 构建自己的 HTTP 网络服务器,并希望在从套接字输入流中读取 http 请求标头时实施一些安全措施。

我正在努力防止有人发送极长的单行标题或荒谬的标题行会导致内存溢出或其他您不想要的事情。

我目前正在尝试通过将 8kb 的数据读入字节数组并解析我刚刚创建的缓冲区中的所有标头来做到这一点。 但据我所知,这意味着您的输入流的当前偏移量总是从起点开始 8kb,即使您只有 100 字节的标头。

我目前的代码:

InputStream stream = socket.getInputStream();

HashMap<String, String> headers = new HashMap<String, String>();

byte [] buffer = new byte[8*1024];

stream.read( buffer , 0 , 8*1024);
ByteArrayInputStream bytestream = new ByteArrayInputStream( buffer );
InputStreamReader streamReader = new InputStreamReader( bytestream );
BufferedReader reader = new BufferedReader( streamReader );

String requestline = reader.readLine();

for ( ;; )
{
    String line = reader.readLine();
    if ( line.equals( "" ) )
        break;

    String[] header = line.split( ":" , 2 );

    headers.put( header[0] , header[1] ); //TODO: check for bad header
}

//if contentlength > 0
//      read body

所以我的问题是,我如何确定我正在从输入流中的正确位置开始读取正文数据(如果有)?

我并没有经常使用流,所以我对它们没有什么感觉,而且谷歌到目前为止也没有帮助

【问题讨论】:

  • 您可以查看 Apache Tomcat 源代码,了解他们是如何做到的

标签: java security http-headers


【解决方案1】:

我自己想出了一个答案。 (比我想象的要容易)

如果我猜它没有缓冲(我不知道什么时候缓冲了),但它可以工作。

public class SafeHttpHeaderReader
{   
    public static final int MAX_READ = 8*1024;
    private InputStream stream;
    private int bytesRead;

    public SafeHttpHeaderReader(InputStream stream)
    {
        this.stream = stream;
        bytesRead = 0;
    }

    public boolean hasReachedMax()
    {
        return bytesRead >= MAX_READ;
    }

    public String readLine() throws IOException, Http400Exception
    {
        String s = "";

        while(bytesRead < MAX_READ)
        {
            String n = read();

            if(n.equals( "" ))
                break;

            if(n.equals( "\r" ))
            {
                if(read().equals( "\n" ))
                    break;

                throw new Http400Exception();
            }
            s += n;
        }

        return s;
    }

    private String read() throws IOException
    {
        byte b = readByte();

        if(b == -1)
            return "";

        return new String( new byte[]{b} , "ASCII");
    }

    private byte readByte() throws IOException
    {
        byte b = (byte) stream.read();
        bytesRead ++;
        return b;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 2014-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多