it-swarm.com.de

Kann ich einige konkrete URLs aus <URL-Muster> in <Filter-Mapping> ausschließen?

Ich möchte, dass ein konkreter Filter für alle URLs mit Ausnahme eines Betons angewendet wird (d. H. Für /* mit Ausnahme von /specialpath).

Gibt es eine Möglichkeit das zu tun?


beispielcode:

<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>
117
Roman

Die Standard-Servlet-API unterstützt diese Funktion nicht. Sie können entweder einen Umschreib-URL-Filter wie Tuckeys einen verwenden (der mod_rewrite von Apache HTTPD sehr ähnlich ist) oder eine Prüfung in der doFilter()-Methode des Filters, der auf /* hört.

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.
}

Sie können die zu ignorierenden Pfade ggf. als init-param des Filters angeben, damit Sie ihn im web.xml trotzdem steuern können. Sie können es wie folgt in den Filter bekommen:

private String pathToBeIgnored;

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

Wenn der Filter Teil einer Drittanbieter-API ist und Sie ihn daher nicht ändern können, ordnen Sie ihn einem spezifischeren url-pattern zu, z. /otherfilterpath/* und erstellen Sie einen neuen Filter für /*, der an den Pfad weitergeleitet wird, der dem Drittanbieter-Filter entspricht.

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

Um zu vermeiden, dass dieser Filter sich in einer Endlosschleife aufruft, müssen Sie ihn nur auf REQUEST und den 3rd Party-Filter nur auf FORWARD abhören (Dispatch).

Siehe auch:

142
BalusC

Ich habe einen Ansatz von Eric Daugherty beschrieben verwendet: Ich habe ein spezielles Servlet erstellt, das immer mit 403-Code antwortet und dessen Zuordnung vor dem allgemeinen setzt.

Mapping-Fragment:

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

Und die Servlet-Klasse:

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

Dieser Ansatz funktioniert, wenn Sie einen bestimmten und alle folgenden Filter verhindern möchten. Es sollte gut funktionieren, wenn Sie z. möchten einige Inhalte als statische Ressourcen in Ihrem Servlet-Container bereitstellen, anstatt Ihre Anwendungslogik zuzulassen (durch einen Filter wie GuiceFilter):

Ordnen Sie den Ordner mit Ihren statischen Ressourcendateien dem Standardservlet zu. Erstellen Sie einen Servlet-Filter und legen Sie ihn vor dem GuiceFilter in Ihre web.xml. In Ihrem erstellten Filter können Sie trennen, indem Sie einige Anforderungen an den GuiceFilter und andere direkt an den Dispatcher weiterleiten. Beispiel folgt ...

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

Wenn Sie nur einen Schritt in der Filterkette überspringen möchten und die folgenden Schritte beibehalten möchten, funktioniert dies leider nicht.

6
kvitso

Ich denke nicht, dass Sie das können, die einzige andere Konfigurationsalternative ist das Auflisten der Pfade, die Sie filtern möchten. Statt /* könnten Sie einige für /this/* und /that/* usw. hinzufügen. Dies führt jedoch nicht zu einer ausreichenden Lösung Du hast viele Wege.

Sie können dem Filter einen Parameter hinzufügen, der einen Ausdruck (wie einen regulären Ausdruck) bereitstellt, mit dem die Filterfunktion für die übereinstimmenden Pfade übersprungen wird. Der Servlet-Container ruft Ihren Filter weiterhin für diese URLs auf, aber Sie werden es tun haben Sie eine bessere Kontrolle über die Konfiguration.

Bearbeiten

Nachdem Sie nun erwähnt haben, dass Sie keine Kontrolle über den Filter haben, können Sie entweder von diesem Filter erben, der super-Methoden in seinen Methoden aufruft, es sei denn, der URL-Pfad, den Sie überspringen möchten, ist vorhanden und folgt der Filterkette, wie @BalusC, vorgeschlagen Erstellen Sie einen Filter, der Ihren Filter instanziiert und unter denselben Umständen delegiert. In beiden Fällen würden die Filterparameter sowohl den hinzugefügten Ausdrucksparameter als auch die des Filters enthalten, von dem Sie erben oder an den sie delegieren.

Das Erstellen eines Delegierungsfilters (eines Wrappers) hat den Vorteil, dass Sie die Filterklasse des umschlossenen Filters als Parameter hinzufügen und in anderen Situationen wie dieser wiederverwenden können.

3
rsp

Ich musste auch anhand des URL-Musters (/ {servicename}/api/stats /) in Java-Code filtern.

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

Aber es ist bizarr, dass dieses Servlet kein anderes URL-Muster als (/ *) unterstützt. Dies sollte ein sehr häufiger Fall für Servlet-APIs sein! 

2
Sindhu

Ich habe das gleiche Problem gesehen, aber unten finde ich eine Antwort.

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

auf diese Weise müssen Sie die konkrete Filterklasse nicht belästigen.

0
nelson

Wenn Sie aus irgendeinem Grund die ursprüngliche Filterzuordnung nicht ändern können (in meinem Fall "/ *") und Sie zu einem nicht veränderbaren Filter eines Drittanbieters wechseln, finden Sie Folgendes hilfreich

  • Fangen Sie den zu überbrückenden Pfad ab
  • Springt zum letzten Ring der Filterkette (das Servlet selbst) und führt es aus
  • Das Überspringen erfolgt über Reflektion, wobei die Containerinstanzen im Debugmodus überprüft werden 

Folgendes funktioniert in 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();
              }           
          }   
      }
0
robermann