[java] <filter-mapping> 내부의 <url-pattern>에서 구체적인 URL을 제외 할 수 있습니까?

콘크리트 하나를 제외한 모든 URL에 콘크리트 필터를 적용하고 싶습니다 (예 : /*제외 /specialpath).

그렇게 할 가능성이 있습니까?


샘플 코드 :

<filter>
    <filter-name>SomeFilter</filter-name>
    <filter-class>org.somproject.AFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SomeFilter</filter-name>
    <url-pattern>/*</url-pattern>   <!-- the question is: how to modify this line?  -->
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>



답변

표준 서블릿 API는이 기능을 지원하지 않습니다. Tuckey 와 유사한 rewrite-URL 필터를 사용하거나 (아파치 HTTPD와 매우 유사한 mod_rewrite) doFilter()필터 청취 방법에 체크를 추가 할 수 있습니다 /*.

String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
    chain.doFilter(request, response); // Just continue chain.
} else {
    // Do your business stuff here for all paths other than /specialpath.
}

필요한 경우 무시할 경로를 init-param필터로 지정하여 web.xml어쨌든 제어 할 수 있습니다 . 다음과 같이 필터에서 얻을 수 있습니다.

private String pathToBeIgnored;

public void init(FilterConfig config) {
    pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}

필터는 제 3 자 API의 일부이며 따라서 당신은보다 구체적인에서 매핑, 수정할 수없는 경우 url-pattern, 예를 들어, /otherfilterpath/*및에 새로운 필터를 생성 /*하는 앞으로 제 3 자 필터와 일치하는 경로를.

String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
    chain.doFilter(request, response); // Just continue chain.
} else {
    request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response);
}

이 필터가 무한 루프에서 자신을 호출하지 않도록하려면 필터 REQUEST만 수신하고 (제외) 필터 를 써야 FORWARD합니다.

또한보십시오:


답변

Eric Daugherty가 설명 한 접근 방식을 사용했습니다 . 항상 403 코드로 응답하고 일반적인 매핑 앞에 매핑하는 특수 서블릿을 만들었습니다.

매핑 조각 :

  <servlet>
    <servlet-name>generalServlet</servlet-name>
    <servlet-class>project.servlet.GeneralServlet</servlet-class>
  </servlet>
 <servlet>
    <servlet-name>specialServlet</servlet-name>
    <servlet-class>project.servlet.SpecialServlet</servlet-class>
 </servlet>
 <servlet-mapping>
    <servlet-name>specialServlet</servlet-name>
    <url-pattern>/resources/restricted/*</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
    <servlet-name>generalServlet</servlet-name>
    <url-pattern>/resources/*</url-pattern>
 </servlet-mapping>

그리고 서블릿 클래스 :

public class SpecialServlet extends HttpServlet {
    public SpecialServlet() {
        super();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
    }
}


답변

이 방법은 특정 필터와 다음 필터를 모두 방지하려는 경우에 작동합니다. 예를 들어 잘 작동합니다. GuiceFilter와 같은 필터를 통해 응용 프로그램 논리를 허용하지 않고 서블릿 컨테이너 내에서 일부 내용을 정적 리소스로 제공하려고합니다.

정적 자원 파일이있는 폴더를 기본 서블릿에 맵핑하십시오. 서블릿 필터를 만들어 web.xml에서 GuiceFilter 앞에 놓습니다. 생성 된 필터에서 일부 요청을 GuiceFilter로 전달하는 것과 다른 요청을 디스패처로 직접 전달하는 것을 분리 할 수 ​​있습니다. 예는 다음과 같습니다.

web.xml

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>StaticResourceFilter</filter-name>
    <filter-class>com.project.filter.StaticResourceFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>StaticResourceFilter</filter-name>
    <url-pattern>/static/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

StaticResourceFilter.class

public class StaticResourceFilter implements Filter {

    private final static Logger LOGGER = LoggerFactory.getLogger(StaticResourceFilter.class);

    private static final String RESOURCE_PATH = "/static/";
    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
        LOGGER.info("StaticResourceFilter initialized");
    }

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

        String path = ((HttpServletRequest) request).getServletPath();
        if (path.toLowerCase().startsWith(RESOURCE_PATH)) {
            request.getRequestDispatcher(path).forward(request, response);
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
        LOGGER.info("StaticResourceFilter destroyed");
    }
}

불행히도 다음 단계를 유지하면서 필터 체인에서 한 단계를 건너 뛰려면 작동하지 않습니다.


답변

나는 당신이 할 수있는 유일한 다른 구성 대안 그래서 대신에, 당신은 필터링하려는 경로를 열거하는 것입니다 생각하지 않는 /*몇 가지를 추가 할 수 있습니다 당신 /this/*/that/*등,하지만 당신은 많이있을 때 충분한 솔루션으로 이어질하지 않습니다 그 길의.

일치하는 경로에 대한 필터 기능을 건너 뛰는 데 사용되는 표현식 (예 : 정규식)을 제공하는 매개 변수를 필터에 추가하면됩니다. 서블릿 컨테이너는 여전히 해당 URL에 대한 필터를 호출하지만 구성을보다 잘 제어 할 수 있습니다.

편집하다

필터에 대한 제어 권한이 없다고 언급 super했으므로 건너 뛸 URL 경로가 있고 @BalusC 제안 된 필터 체인을 따르는 경우를 제외하고 메소드에서 해당 필터 호출 메소드에서 상속 하거나 빌드 할 수 있습니다. 동일한 상황에서 필터를 인스턴스화하고 위임하는 필터. 두 경우 모두 필터 매개 변수에는 추가 한 식 매개 변수와 상속하거나 위임 한 필터의 매개 변수가 모두 포함됩니다.

위임 필터 (래퍼)를 만들면 래핑 된 필터의 필터 클래스를 매개 변수로 추가하고 이와 같은 다른 상황에서 재사용 할 수 있다는 장점이 있습니다.


답변

또한 Java 코드의 URL 패턴 (/ {servicename} / api / stats /)을 기준으로 필터링해야했습니다.

if (path.startsWith("/{servicename}/api/statistics/")) {
validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token"));
filterChain.doFilter(request, response);
}

그러나 그 기괴한 서블릿은 (/ *) 이외의 URL 패턴을 지원하지 않습니다. 이것은 서블릿 API의 경우 매우 일반적인 경우입니다!


답변

같은 문제가 발생했지만 아래에 답변이 표시됩니다.

web.xml

 <!-- set this param value for the filter-->
    <init-param>
            <param-name>freePages</param-name>
            <param-value>
            MainFrame.jsp;
            </param-value>
    </init-param>

filter.java

strFreePages = config.getInitParameter("freePages"); //get the exclue pattern from config file
isFreePage(strRequestPage)  //decide the exclude path

이런 식으로 콘크리트 필터 클래스를 괴롭힐 필요가 없습니다.


답변

어떤 이유로 든 원래 필터 매핑 (내 경우에는 “/ *”)을 변경할 수없고 변경할 수없는 타사 필터로 디스패치하는 경우 다음을 유용하게 사용할 수 있습니다.

  • 우회 될 경로를 가로 채십시오
  • 필터 체인의 마지막 링 (서블릿 자체)으로 건너 뛰어 실행
  • 건너 뛰기는 리플렉션을 통해 수행되며 디버그 모드에서 컨테이너 인스턴스를 검사합니다.

다음은 Weblogic 12.1.3에서 작동합니다.

      import org.apache.commons.lang3.reflect.FieldUtils;
      import javax.servlet.Filter;

      [...]

      @Override
      public void doFilter(ServletRequest request, ServletRespons response, FilterChain chain) throws IOException, ServletException {
          String path = ((HttpServletRequest) request).getRequestURI();

          if(!bypassSWA(path)){
              swpFilterHandler.doFilter(request, response, chain);

          } else {
              try {
                  ((Filter) (FieldUtils.readField(
                                (FieldUtils.readField(
                                        (FieldUtils.readField(chain, "filters", true)), "last", true)), "item", true)))
                  .doFilter(request, response, chain);
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              }
          }
      }