在java中安全地读取http请求标头

时间:2014-10-23 17:47:30

标签: java security http-headers

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

我试图阻止有人发送极长的单行标题或荒谬的标题行会导致内存溢出或其他你不想要的事情。

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

我到目前为止的代码:

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

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

我并没有完全使用流媒体,所以我对他们并没有真正的感觉,谷歌到目前为止还没有帮助

1 个答案:

答案 0 :(得分:0)

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

如果我猜它没有缓冲(我不知道什么时候缓冲了什么)但是它有效。

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;
    }
}