Java 在 servlet 过滤器中向请求添加 HTTP 标头

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2811769/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:08:18  来源:igfitidea点击:

Adding an HTTP Header to the request in a servlet filter

javaservletsjakarta-eeservlet-filters

提问by Mason

I'm integrating with an existing servlet that pulls some properties out of the HTTP header. Basically, I'm implementing an interface that doesn't have access to the actual request, it just has access to a map of k->v for the HTTP headers.

我正在与一个现有的 servlet 集成,该 servlet 从 HTTP 标头中提取一些属性。基本上,我正在实现一个无法访问实际请求的接口,它只能访问 HTTP 标头的 k->v 映射。

I need to pass in a request parameter. The plan is to use a servlet filter to go from parameter to header value but of course the HttpServletRequest object doesn't have an addHeader() method.

我需要传入一个请求参数。计划是使用 servlet 过滤器从参数到标头值,但当然 HttpServletRequest 对象没有 addHeader() 方法。

Any ideas?

有任何想法吗?

采纳答案by BalusC

Extend HttpServletRequestWrapper, override the header getters to return the parameters as well:

Extend HttpServletRequestWrapper,覆盖标头 getter 以返回参数:

public class AddParamsToHeader extends HttpServletRequestWrapper {
    public AddParamsToHeader(HttpServletRequest request) {
        super(request);
    }

    public String getHeader(String name) {
        String header = super.getHeader(name);
        return (header != null) ? header : super.getParameter(name); // Note: you can't use getParameterValues() here.
    }

    public Enumeration getHeaderNames() {
        List<String> names = Collections.list(super.getHeaderNames());
        names.addAll(Collections.list(super.getParameterNames()));
        return Collections.enumeration(names);
    }
}

..and wrap the original request with it:

..并用它包装原始请求:

chain.doFilter(new AddParamsToHeader((HttpServletRequest) request), response);


That said, I personally find this a bad idea. Rather give it direct access to the parameters or pass the parameters to it.

也就是说,我个人认为这是一个坏主意。而是让它直接访问参数或将参数传递给它。

回答by laz

You'll have to use an HttpServletRequestWrapper:

您必须使用HttpServletRequestWrapper

public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
    final HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(httpRequest) {
        @Override
        public String getHeader(String name) {
            final String value = request.getParameter(name);
            if (value != null) {
                return value;
            }
            return super.getHeader(name);
        }
    };
    chain.doFilter(wrapper, response);
}

Depending on what you want to do you may need to implement other methods of the wrapper like getHeaderNamesfor instance. Just be aware that this is trusting the client and allowing them to manipulate any HTTP header. You may want to sandbox it and only allow certain header values to be modified this way.

根据您想要做什么,您可能需要实现包装器的其他方法,getHeaderNames例如。请注意,这是信任客户端并允许他们操作任何 HTTP 标头。您可能希望对其进行沙盒处理,并且只允许以这种方式修改某些标头值。

回答by Wolfgang Fahl

as https://stackoverflow.com/users/89391/mikupointed out this would be a complete ServletFilter example that uses the code that also works for Jersey to add the remote_addr header.

正如https://stackoverflow.com/users/89391/miku指出的那样,这将是一个完整的 ServletFilter 示例,它使用同样适用于 Jersey 的代码添加 remote_addr 标头。

package com.bitplan.smartCRM.web;

import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * 
 * @author wf
 * 
 */
public class RemoteAddrFilter implements Filter {

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HeaderMapRequestWrapper requestWrapper = new HeaderMapRequestWrapper(req);
        String remote_addr = request.getRemoteAddr();
        requestWrapper.addHeader("remote_addr", remote_addr);
        chain.doFilter(requestWrapper, response); // Goes to default servlet.
    }

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

    }

    // https://stackoverflow.com/questions/2811769/adding-an-http-header-to-the-request-in-a-servlet-filter
    // http://sandeepmore.com/blog/2010/06/12/modifying-http-headers-using-java/
    // http://bijubnair.blogspot.de/2008/12/adding-header-information-to-existing.html
    /**
     * allow adding additional header entries to a request
     * 
     * @author wf
     * 
     */
    public class HeaderMapRequestWrapper extends HttpServletRequestWrapper {
        /**
         * construct a wrapper for this request
         * 
         * @param request
         */
        public HeaderMapRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        private Map<String, String> headerMap = new HashMap<String, String>();

        /**
         * add a header with given name and value
         * 
         * @param name
         * @param value
         */
        public void addHeader(String name, String value) {
            headerMap.put(name, value);
        }

        @Override
        public String getHeader(String name) {
            String headerValue = super.getHeader(name);
            if (headerMap.containsKey(name)) {
                headerValue = headerMap.get(name);
            }
            return headerValue;
        }

        /**
         * get the Header names
         */
        @Override
        public Enumeration<String> getHeaderNames() {
            List<String> names = Collections.list(super.getHeaderNames());
            for (String name : headerMap.keySet()) {
                names.add(name);
            }
            return Collections.enumeration(names);
        }

        @Override
        public Enumeration<String> getHeaders(String name) {
            List<String> values = Collections.list(super.getHeaders(name));
            if (headerMap.containsKey(name)) {
                values.add(headerMap.get(name));
            }
            return Collections.enumeration(values);
        }

    }

}

web.xml snippet:

web.xml 片段:

<!--  first filter adds remote addr header -->
<filter>
    <filter-name>remoteAddrfilter</filter-name>
    <filter-class>com.bitplan.smartCRM.web.RemoteAddrFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>remoteAddrfilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>