Puis-je exclure certains béton url de l'intérieur?
je veux qu'un filtre en béton soit appliqué pour toutes les urls à l'exception d'un filtre en béton (i.e. pour /*
à l'exception de /specialpath
).
est-il possible de faire cela?
exemple de code:
<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>
7 réponses
l'API Servlet standard ne supporte pas cette fonctionnalité. Vous pouvez utiliser soit un filtre rewrite-URL pour cela comme , celui de Tuckey (qui est très similaire à mod_rewrite
D'Apache HTTPD), soit ajouter une vérification dans la méthode doFilter()
de L'écoute du filtre sur /*
.
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.
}
vous pouvez si nécessaire spécifier les chemins-à-être-ignoré comme un init-param
du filtre afin que vous puissiez le contrôler dans le web.xml
de toute façon. Vous pouvez l'obtenir dans le filtre comme suit:
private String pathToBeIgnored;
public void init(FilterConfig config) {
pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}
si le filtre fait partie de L'API de tiers et que vous ne pouvez donc pas le modifier, alors mappez-le sur un url-pattern
plus spécifique , par exemple /otherfilterpath/*
et créez un nouveau filtre sur /*
qui avance vers le chemin correspondant au filtre de tiers.
String 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'appeler lui-même dans une boucle infinie, vous devez laisser écouter (expédition) sur REQUEST
, et le filtre tiers sur FORWARD
seulement.
voir aussi:
j'ai utilisé une approche décrite par Eric Daugherty : j'ai créé un servlet spécial qui répond toujours avec 403 code et mettre sa cartographie avant le général.
fragment de cartographie:
<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>
et la classe 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 voulez empêcher un certain filtre et tous les suivants. Il devrait bien fonctionner si par exemple vous. vous voulez servir du contenu comme des ressources statiques dans votre conteneur servlet au lieu de laisser votre logique d'application (à travers un filtre comme GuiceFilter):
mappez le dossier avec vos fichiers de ressources statiques vers le servlet par défaut. Créer un filtre servlet et le mettre avant le GuiceFilter dans votre web.XML. Dans votre créé un filtre, vous pouvez séparer l'envoi de certaines requêtes à GuiceFilter et d'autres directement au répartiteur. L'exemple qui suit...
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.classe
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");
}
}
malheureusement si vous voulez simplement sauter une seule étape dans la chaîne de filtrage tout en gardant ceux qui suivent, cela ne fonctionnera pas.
Je ne pense pas que vous pouvez, la seule autre alternative de configuration est d'énumérer les chemins que vous voulez filtrer, donc au lieu de /*
vous pouvez en ajouter pour /this/*
et /that/*
etc, mais cela ne mènera pas à une solution suffisante quand vous avez beaucoup de ces chemins.
ce que vous pouvez faire est d'ajouter un paramètre au filtre fournissant une expression (comme une expression régulière) qui est utilisée pour sauter la fonctionnalité de filtre pour les chemins égaler. Le conteneur servlet appellera toujours votre filtre pour ces URLs 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, ce que vous pouvez faire est soit hériter de ce filtre appelant super
méthodes dans ses méthodes sauf lorsque le chemin url que vous voulez sauter est présent et suivre la chaîne de filtre comme @BalusC proposé, ou construire un filtre qui instancie votre filtre et délégués dans les mêmes circonstances. Dans les deux cas, les paramètres du filtre comprendraient à 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 construire un filtre de délégation (un wrapper) est que vous pouvez ajouter la classe de filtre du filtre enveloppé comme paramètre et le réutiliser dans d'autres situations comme celle-ci.
j'ai également dû filtrer sur la base du modèle D'URL(/{servicename}/api/stats/)en code java .
if (path.startsWith("/{servicename}/api/statistics/")) {
validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token"));
filterChain.doFilter(request, response);
}
mais son bizarre, c'est que servlet ne supporte pas d'url pattern autre que ( / * ), cela devrait être un cas très courant pour les API servlet !
j'ai rencontré le MÊME PROBLÈME, MAIS je trouve un anwser montrant ci-dessous.
web.xml
<!-- set this param value for the filter-->
<init-param>
<param-name>freePages</param-name>
<param-value>
MainFrame.jsp;
</param-value>
</init-param>
du filtre.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 de filtre en béton.
si pour une raison quelconque vous ne pouvez pas changer le mappage du filtre d'origine ("/*"dans mon cas) et que vous envoyez à un filtre tiers immuable, vous pouvez trouver utile ce qui suit:
- Intercepter le chemin pour être ignoré
- passer et exécuter le dernier anneau de la chaîne de filtre (le servlet lui-même)
- Le saut se fait via la réflexion, à l'inspection du conteneur instances en mode de débogage
Les ouvrages suivants, en 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(); } } }