如何在过滤器中更改http响应的正文 [英] How to alter the body of a http response in a filter

查看:276
本文介绍了如何在过滤器中更改http响应的正文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用过滤器来检查响应正文中的HTML标签.问题是,如果我更改过滤器中的主体,则到达客户端时它不会被更改.我尝试了此处显示的解决方案:

I am attempting to use a filter to check for HTML tags in a response body. The problem is that if I alter the body in the filter, it isn't altered when it gets to the client. I tried the solution shown here: Looking for an example for inserting content into the response using a servlet filter but it didn't help.

我有两个过滤器. SecureWrapperFilter将请求/响应对象包装在我们的自定义包装器中,而XSSFilter使用OWASP编码对html内容进行编码.过滤器如下所示:

I have two filters. SecureWrapperFilter wraps the request/response objects in our custom wrapper, and XSSFilter uses OWASP encode to encode for html content. The filters look like this:

public class SecureWrapperFilter implements Filter {

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response,
        final FilterChain chain) throws IOException, ServletException
    {
        final ServletRequestWrapper securityRequest =
            new ServletRequestWrapper((HttpServletRequest)request);
        final ServletResponseWrapper securityResponse =
            new ServletResponseWrapper((HttpServletResponse)response);
        ESAPI.httpUtilities().setCurrentHTTP(securityRequest, securityResponse);
        chain.doFilter(ESAPI.currentRequest(), ESAPI.currentResponse());
    }

    @Override
    public void destroy() {
    }
}

和:

public class XSSFilter implements Filter {

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response,
        final FilterChain chain) throws IOException, ServletException
    {      
        final ServletRequestWrapper requestWrapper = (ServletRequestWrapper)request;
        final String body = Encode.forHtmlContent(requestWrapper.getBody());
        requestWrapper.setBody(body);
        chain.doFilter(requestWrapper, response);
        final ServletResponseWrapper responseWrapper = (ServletResponseWrapper)response;
        final byte[] copy = responseWrapper.getCopy();
        final String oldBody = new String(copy, response.getCharacterEncoding());
        final String newBody = Encode.forHtmlContent(oldBody);
        if (!StringUtils.equals(oldBody, newBody)) {
            responseWrapper.getResponse().getOutputStream().write(newBody.getBytes());
        }
    }

    @Override
    public void destroy() {
    }
}

如果添加一些调试日志记录,则可以看到securityResponse在SecureWrapperFilter中具有已修改的主体,但是在客户端,该主体看起来好像从未修改过.

If I add some debug Logging, I can see that the securityResponse has the modified body in the SecureWrapperFilter, but on the client side, the body looks as if it was never modified.

任何建议将不胜感激.谢谢.

Any suggestions would be greatly appreciated. Thanks.

推荐答案

问题是,在我的XSSFilter中,我将新的响应主体附加到旧的响应主体上.这导致像{"x"="y"}{"escapedx"="escapedy")

The problem was that in my XSSFilter, I was appending the new response body onto the old one. This was causing invalid json like {"x"="y"}{"escapedx"="escapedy")

我们的客户端反序列化器仅打印第一个json对象,因此{"x"=y"}是我们在客户端看到的全部内容.

Our client deserializer was only printing the first json object so {"x"=y"} was all we were seeing on the client side.

要解决此问题,我将以下行添加到XSSFilter:

To resolve this problem, I added the following line to the XSSFilter:

responseWrapper.getResponse().resetBuffer();

之前

responseWrapper.getResponse().getOutputStream().write(newBody.getBytes());

这将清除缓冲区,允许我在下面的行上对其进行重写.我在客户端的json现在看起来像:{"escapedx"="escapedy"}

This clears the buffer, allowing me to rewrite it on the line below. My json on the client side now looks like: {"escapedx"="escapedy"}

这篇关于如何在过滤器中更改http响应的正文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆