2012-02-13 15 views
0

私はjavax.servlet.Filterを使ってメッセージを覗いてみました。 javadocツールに応じて正しい動作ですフィルタからMesageをどのように覗くことができますか?

java.lang.IllegalStateException: getReader() has already been called for this request 

:最後にリクエストを受け

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
    BufferedReader reader = request.getReader(); 
    if (reader.markSupported()) { 
     reader.mark(contentLen); 
    } 
    String content = reader.readLine(); 

    // search some pattern 

    if (reader.markSupported()) { 
     reader.reset(); 
    } 
    chain.doFilter(request, response); 
} 

サーブレットは、このexeptionをスローします。

私の質問はどうしたら入力ストリームの内容を読み込むことができますか?

私もテストしていないServletInputStream is = request.getInputStream();

+0

はリクエストのクローンを作成して、クローンを見てもらえますか? –

答えて

1

を試してみましたが、あなたはおそらく

  • 以上のバッファリングリーダーを構築する要求入力ストリームからすべてのバイトを読み、バイト配列に書き込み、
  • ができこのバイト配列は、
  • HttpServletRequestWrapperを構成し、getInputStream()をオーバーライドしてバイト配列のストリームを返します。
  • このラッパーをフィルターチェーンに渡します。
+0

ありがとう、コピーは唯一の方法だと思われます。 – stacker

+0

これは簡単な 'OutOfMemoryError'の脆弱性の穴を開きます。ハッカーは、サーバを完全にダウンさせるためにサーバの利用可能なヒープよりも大きいリクエストボディを送信することができます。 Apache Commons FileUploadが大きなファイルのアップロードを処理する方法を見てみましょう。ファイルアップロードは、部分的にメモリに保存され、一時ディスクに残ります。または、具体的な機能要件に応じて異なるソリューションを探してください。 – BalusC

+0

@BalusC:面白いです。 Tomcatは、通常のリクエストボディの解析でこの問題を回避するために、maxPostSizeを2メガバイトに設定しています。私はOPが同じことをして、読み込みバイト数がX MB以上であれば例外を投げるべきだと思います。 JSONでエンコードされたリクエスト本体をオブジェクトに自動的に変換するWebフレームワークがこの種の最大値を持っているのか、それとも同じ脆弱性が存在するのではないかと思います。 –

0

ServletRequest.getInputStream()ServletRequest.getReader()がすでに呼び出されているいずれかの場合にのいずれか、又は、他の一つは失敗しています。あなたはこの周りをナビゲートするために、単純なのtry-catchを使用することができます。

try { 
    request.getInputStream(); 
} catch (IllegalStateException e) { 
    // someone already called getReader(), so use it instead 
    request.getReader(); 
} 

NOTEを!ストリームまたはリーダをリセット可能にする必要はありません。そのため、バイトを消費すると、チェーン内のどのフィルタやサーブレットでも使用できなくなります。 @JB Nizetからaproach後

+0

これらのJSPや他のサーブレットにすべてのことを伝えるのは難しいです。いいえ、これは本当に実現可能な "回避策"ではありません。実際に何らかの形で実装されていると、文字エンコードを混乱させるでしょう。 – BalusC

1

は、このコードにつながっ:

public class HttpServletRequestCopy extends HttpServletRequestWrapper { 

    private final byte[]  buffer; 

    private ServletInputStream sis; 

    private BufferedReader  reader; 

    public byte[] getBuffer() { 
     return buffer; 
    } 

    public HttpServletRequestCopy(HttpServletRequest request) throws IOException { 
     super(request); 
     final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
     copyStream(request.getInputStream(), byteArrayOutputStream); 
     buffer = byteArrayOutputStream.toByteArray(); 
    } 

    @Override 
    public BufferedReader getReader() throws IOException { 
     if (reader == null) { 
      String characterEncoding = this.getCharacterEncoding(); 
      if (characterEncoding == null) { 
       reader = new BufferedReader(new InputStreamReader(this.getInputStream())); 
      } 
      else { 
       reader = new BufferedReader(new InputStreamReader(this.getInputStream(), characterEncoding)); 
      } 
     } 
     return reader; 
    } 

    @Override 
    public ServletInputStream getInputStream() throws IOException { 
     if (sis == null) { 
      final ByteArrayInputStream bais = new ByteArrayInputStream(buffer); 
      sis = new ServletInputStream() { 
       @Override 
       public int read() throws IOException { 
        return bais.read(); 
       } 
      }; 
     } 
     return sis; 
    } 

    private void copyStream(InputStream input, OutputStream output) throws IOException { 
     final byte[] bytes = new byte[ 1024 ]; 
     int length; 
     while ((length = input.read(bytes)) != -1) { 
      output.write(bytes, 0, length); 
     } 
    } 
} 
関連する問題