2017-08-23 3 views
0

私はSpringブートとフィルタを使用してリクエストをフィルタリングしています。 このフィルタは、リクエストボディからいくつかのデータを読み込んでいるユーザ検証をチェックするために使用されています(これは、HttpServletRequestWrapper実装を使用しています)。 requestWrapperから、私は期待どおりのデータを取得しており、私のサービスはフィルタでうまく動作しています。しかし、成功した場合に、フィルタは、メインコントローラに要求を通過したとき、私はストリーム閉じ、例外を取得していますと、次のように:ここで HttpMessageNotReadableException:ドキュメントを読み取れませんでした:ストリームが閉じました。

o.s.w.s.m.s.DefaultHandlerExceptionResolver - Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Stream closed; nested exception is java.io.IOException: Stream closed 

は、Filterクラスです:

@WebFilter(urlPatterns = {"/getDocs" }) 
public class AuthenticationFilter implements Filter{ 

    private static Logger logger = Logger.getLogger(AuthenticationFilter.class); 

    @Autowired 
    private UserVerificationService userVerificationService; 

    @Override 
    public void destroy() { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void doFilter(ServletRequest arg0, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException { 

     logger.info("checking token in filter"); 
     HttpServletRequest request = (HttpServletRequest) arg0; 
     DocVerificationRequestWrapper myRequestWrapper = new DocVerificationRequestWrapper((HttpServletRequest) request); 
     String body = myRequestWrapper.getBody(); 
     Token token = null; 
     try { 
      JSONObject jsonObj = new JSONObject(body); 
      JSONObject tokenObj = (JSONObject) jsonObj.get("token"); 
      Gson gson = new Gson(); 
      token = gson.fromJson(tokenObj.toString(), Token.class); 

      if(null != token) { 
        if(userVerificationService==null){ 
        ServletContext servletContext = request.getServletContext(); 
        WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext); 
        userVerificationService = webApplicationContext.getBean(UserVerificationService.class); 
       } 
        String verStatus = userVerificationService.verifyUser(token); 
        logger.info("verStatus = "+verStatus); 
        if(verStatus != null && verStatus.equalsIgnoreCase("success")) { 
         chain.doFilter(request, response); 
        }else 
         logger.error("Invalid token"); 
      }else { 
        logger.error("token missing."); 
      } 
     } catch (JSONException e) { 
       logger.error("exception in authetication filter " + e); 
     } 
    } 

    @Override 
    public void init(FilterConfig arg0) throws ServletException { 
     // TODO Auto-generated method stub 

    } 

} 

とここにありますHttpServletRequestWrapperクラス実装クラス:

public class DocVerificationRequestWrapper extends HttpServletRequestWrapper { 
private final String body; 
public DocVerificationRequestWrapper(HttpServletRequest request) throws IOException { 
    super(request); 
    StringBuilder stringBuilder = new StringBuilder(); 
    BufferedReader bufferedReader = null; 
    try { 
    InputStream inputStream = request.getInputStream(); 
    if (inputStream != null) { 
     bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 
     char[] charBuffer = new char[128]; 
     int bytesRead = -1; 
     while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { 
     stringBuilder.append(charBuffer, 0, bytesRead); 
     } 
    } else { 
     stringBuilder.append(""); 
    } 
    } catch (IOException ex) { 
     throw ex; 
    } finally { 
    if (bufferedReader != null) { 
     try { 
     bufferedReader.close(); 
     } catch (IOException ex) { 
     throw ex; 
     } 
    } 
    } 
    body = stringBuilder.toString(); 
} 

@Override 
public ServletInputStream getInputStream() throws IOException { 
    final ByteArrayInputStream byteArrayInputStream = new  ByteArrayInputStream(body.getBytes()); 
    ServletInputStream servletInputStream = new ServletInputStream() { 
    public int read() throws IOException { 
     return byteArrayInputStream.read(); 
    } 

    @Override 
    public boolean isFinished() { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    @Override 
    public boolean isReady() { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    @Override 
    public void setReadListener(ReadListener listener) { 
     // TODO Auto-generated method stub 

    } 
    }; 
    return servletInputStream; 
} 

@Override 
public BufferedReader getReader() throws IOException { 
    return new BufferedReader(new InputStreamReader(this.getInputStream())); 
} 

public String getBody() { 
    return this.body; 
} 
} 

任意の提案、どのようにこのエラーを解決するには?

答えて

1

実際のラッパーをチェーンに渡すのではなく、元のリクエストを渡すからです。これを試してみてください:

明らか
if(verStatus != null && verStatus.equalsIgnoreCase("success")) { 
    chain.doFilter(myRequestWrapper, response); 
} 

ObjectMapperがリクエストボディを読み取ろうとする時に - それはあなたのラッパーで、既に読み込まれているので、すでにクローズされた入力ストリームを要求します。

関連する問題