2010-05-11 3 views
28

HTTP 헤더의 일부 속성을 가져 오는 기존 서블릿과 통합하고 있습니다. 기본적으로, 나는 실제 요청에 접근 할 수없는 인터페이스를 구현하고있다. HTTP 헤더에 대해 k-> v의 맵에 액세스 할 수있다.서블릿 필터의 요청에 HTTP 헤더 추가하기

요청 매개 변수를 전달해야합니다. 계획은 서블릿 필터를 사용하여 매개 변수에서 헤더 값으로 이동하지만 HttpServletRequest 객체에는 addHeader() 메소드가 없습니다.

아이디어가 있으십니까? 나는 개인적으로 말했다

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

:

답변

32

뿐만 아니라 매개 변수를 반환하는 헤더 게터를 오버라이드 (override), HttpServletRequestWrapper 확장 :

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); 
    } 
} 

을 .. 그리고 그것으로 원래 요청을 포장 이것을 나쁜 생각으로 생각하십시오. 매개 변수에 직접 액세스하거나 매개 변수를 전달하십시오. 당신은 예를 들어 getHeaderNames 같은 래퍼의 다른 방법을 구현해야 할 수 있습니다 수행하려는 작업에 따라

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); 
} 

:

+1

나는 그것이 좋은 생각이 아니다라고 생각 중 ... 문제는 그냥 하나의 작은 클래스가 큰 기존의 시스템에 통합 해요입니다. – Mason

+0

실제로 getHeader 메서드를 재정의하는 대신 헤더를 수정하여이 작업을 수행 할 수 있습니까? 그 라인의 아래쪽에있는 getHeader 메소드를 오버 라이딩하는 것처럼 보입니다. – Mason

+2

유일한 방법은 프록시에 대해 행동하고 완전히 새로운 HTTP 요청을 만들고 해당 서블릿의 URL에'java.net.URLConnection'을 사용하여 시작한 다음 응답을 다시 스트리밍하는 것입니다. 별로 효율적이지 않습니다. – BalusC

13

당신은 HttpServletRequestWrapper 사용해야합니다. 이것은 클라이언트를 신뢰하고 모든 HTTP 헤더를 조작 할 수있게한다는 것을 알아 두십시오. 샌드 박스를 사용하여 특정 헤더 값만이 방식으로 수정되도록 허용 할 수 있습니다.

+1

getHeader를 재정의하는 대신 실제로 헤더를 수정하여이 작업을 수행하는 방법이 있습니까? 방법? 그 라인의 아래쪽에있는 getHeader 메소드를 오버 라이딩하는 것처럼 보입니다. – Mason

+0

아마도 web.xml에서 필터의 순서를 바꾸어야 할 것입니다. 이것을 체인의 마지막 부분으로 만드십시오. – laz

12

as https://stackoverflow.com/users/89391/miku 이것은 Jersey가 remote_addr 헤더를 추가하는 코드도 사용하는 완전한 ServletFilter 예제입니다.

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의 조각 :

<!-- 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>