Je veux qu’un filtre concret soit appliqué pour toutes les URL sauf pour un béton (c.-à-d. Pour /*
sauf pour /specialpath
).
Est-il possible de le faire?
exemple de code:
SomeFilter org.somproject.AFilter SomeFilter /* REQUEST FORWARD
L’API Servlet standard ne prend pas en charge cette fonctionnalité. Vous voudrez peut-être utiliser un filtre de ré-écriture-URL comme celui de Tuckey (qui est très similaire au mod_rewrite
Apache HTTPD), ou append une vérification dans la méthode doFilter()
du filtre d’écoute sur /*
.
Ssortingng 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. }
Vous pouvez si nécessaire spécifier les chemins d’access à ignorer en tant que init-param
du filtre afin de pouvoir le contrôler dans le web.xml
. Vous pouvez l’obtenir dans le filtre comme suit:
private Ssortingng pathToBeIgnored; public void init(FilterConfig config) { pathToBeIgnored = config.getInitParameter("pathToBeIgnored"); }
Si le filtre fait partie de l’API tierce et que vous ne pouvez donc pas le modifier, /otherfilterpath/*
sur un url-pattern
plus spécifique, par exemple /otherfilterpath/*
et créez un nouveau filtre sur /*
qui avance vers le chemin correspondant au 3ème filtre de partie.
Ssortingng path = ((HttpServletRequest) request).getRequestURI(); if (path.startsWith("/specialpath/")) { chain.doFilter(request, response); // Just continue chain. } else { request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response); }
Pour éviter que ce filtre s’appelle lui-même dans une boucle infinie, vous devez le laisser écouter (dispatch) uniquement sur REQUEST
et le filtre tiers sur FORWARD
uniquement.
J’ai utilisé une approche décrite par Eric Daugherty : j’ai créé un servlet spécial qui répond toujours avec le code 403 et place son mappage avant le général.
Fragment de cartographie:
generalServlet project.servlet.GeneralServlet specialServlet project.servlet.SpecialServlet specialServlet /resources/ressortingcted/* generalServlet /resources/*
Et la classe de servlet:
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); } }
Cette approche fonctionne lorsque vous souhaitez empêcher un certain filtre et tous les suivants. Cela devrait bien fonctionner si vous, par exemple. Vous souhaitez diffuser du contenu sous forme de ressources statiques dans votre conteneur de servlets au lieu de laisser votre logique applicative (via un filtre comme GuiceFilter):
Mappez le dossier avec vos fichiers de ressources statiques sur le servlet par défaut. Créez un filtre de servlet et placez-le avant le filtre GuiceFilter dans votre web.xml. Dans votre filtre créé, vous pouvez séparer le transfert de certaines requêtes vers le GuiceFilter et d’autres directement vers le répartiteur. Exemple suit …
web.xml
default /static/* StaticResourceFilter com.project.filter.StaticResourceFilter StaticResourceFilter /static/* guiceFilter com.google.inject.servlet.GuiceFilter guiceFilter /*
StaticResourceFilter.class
public class StaticResourceFilter implements Filter { private final static Logger LOGGER = LoggerFactory.getLogger(StaticResourceFilter.class); private static final Ssortingng 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 { Ssortingng 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"); } }
Malheureusement, si vous voulez simplement sauter une seule étape de la chaîne de filtrage tout en conservant celles qui suivent, cela ne fonctionnera pas.
Je ne pense pas que vous le pouvez, la seule autre alternative de configuration est d’énumérer les chemins que vous voulez filtrer, donc au lieu de /*
vous pouvez en append pour /this/*
et /that/*
etc t conduire à une solution suffisante lorsque vous avez beaucoup de ces chemins.
Ce que vous pouvez faire est d’append un paramètre au filtre en fournissant une expression (comme une expression régulière) qui est utilisée pour ignorer la fonctionnalité de filtre pour les chemins d’access correspondants. Le conteneur de servlets appellera toujours votre filtre pour ces URL, mais vous aurez un meilleur contrôle sur la configuration.
modifier
Maintenant que vous mentionnez que vous n’avez aucun contrôle sur le filtre, vous pouvez soit hériter de ce filtre en appelant les méthodes super
dans ses méthodes, sauf lorsque le chemin d’URL que vous voulez ignorer est présent et suivre la chaîne de filtrage proposée, ou construire un filtre qui instancie votre filtre et vos delegates dans les mêmes circonstances. Dans les deux cas, les parameters de filtre incluent à la fois le paramètre d’expression que vous ajoutez et ceux du filtre dont vous héritez ou auquel vous déléguez.
L’avantage de créer un filtre de délégation (un wrapper) est que vous pouvez append la classe de filtre du filtre encapsulé en tant que paramètre et le réutiliser dans d’autres situations comme celle-ci.
J’ai également dû filtrer en fonction du modèle d’URL (/ {servicename} / api / stats /) dans le code Java.
if (path.startsWith("/{servicename}/api/statistics/")) { validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token")); filterChain.doFilter(request, response); }
Mais c’est bizarre, cette servlet ne supporte pas le modèle d’URL autre que (/ *), cela devrait être un cas très courant pour les API de servlet!
J’ai rencontré le même problème, mais je trouve une réponse ci-dessous.
web.xml
freePages MainFrame.jsp;
filter.java
strFreePages = config.getInitParameter("freePages"); //get the exclue pattern from config file isFreePage(strRequestPage) //decide the exclude path
De cette façon, vous n’avez pas à harceler la classe concrète Filter.
Si, pour une raison quelconque, vous ne pouvez pas modifier le mappage du filtre d’origine (“/ *” dans mon cas) et que vous expédiez vers un filtre tiers non modifiable, vous pouvez trouver utile:
Les travaux suivants dans 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 { Ssortingng 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(); } } }
L’API de servlet ne prend pas en charge la fonctionnalité d’exclusion par défaut, mais vous pouvez le faire par programmation:
Cet article: Comment exclure une URL d’un filtre explique en détail l’approche et fournit des exemples de personnalisation des filtres personnalisés et tiers.