简体   繁体   English

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

[英]Adding an HTTP Header to the request in a servlet filter

I'm integrating with an existing servlet that pulls some properties out of the HTTP header. 我正在与现有的servlet集成,从而将一些属性从HTTP头中拉出来。 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. 基本上,我正在实现一个无法访问实际请求的接口,它只能访问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? 有任何想法吗?

Extend HttpServletRequestWrapper , override the header getters to return the parameters as well: 扩展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. 而是让它直接访问参数或将参数传递给它。

as https://stackoverflow.com/users/89391/miku pointed 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>

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 getHeaderNames for instance. 根据您的要求,您可能需要实现包装器的其他方法,例如getHeaderNames Just be aware that this is trusting the client and allowing them to manipulate any HTTP header. 请注意,这是信任客户端并允许它们操纵任何HTTP头。 You may want to sandbox it and only allow certain header values to be modified this way. 您可能希望对其进行沙箱处理,并且仅允许以这种方式修改某些标头值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM