java - dofilter - servlet security filter example
¿Puedo excluir algunas URL concretas de<url-pattern> dentro de<filter-mapping>? (8)
Este enfoque funciona cuando desea evitar un determinado filtro y todos los siguientes. Debería funcionar bien si, por ejemplo. desea servir algo de contenido como recursos estáticos dentro de su contenedor de servlets en lugar de dejar que su aplicación lógica (a través de un filtro como GuiceFilter):
Asigne la carpeta con sus archivos de recursos estáticos al servlet predeterminado. Cree un filtro de servlet y colóquelo antes de GuiceFilter en su web.xml. En su filtro creado, puede separar entre reenviar algunas solicitudes al GuiceFilter y otras directamente al despachador. El ejemplo sigue ...
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");
}
}
Desafortunadamente, si solo quiere omitir un solo paso en la cadena de filtros mientras mantiene los que siguen, esto no funcionará.
Quiero que se aplique un filtro de concreto para todas las URL excepto para un concreto (es decir, para /*
excepción de /specialpath
).
¿Hay una posibilidad de hacer eso?
Código de muestra:
<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>
He encontrado el mismo problema, pero encuentro una letra que se muestra a continuación.
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
de esta manera no tienes que acosar a la clase de filtro concreta.
La API de Servlet estándar no es compatible con esta instalación. Puede usar un filtro de reescritura-URL para esto como el de Tuckey (que es muy similar a la mod_rewrite
Apache HTTPD), o para agregar una doFilter()
en el método doFilter()
del filtro que escucha en /*
.
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.
}
Si es necesario, puede especificar las rutas a ser ignoradas como init-param
del filtro para que pueda controlarlo en el web.xml
todos modos. Puede obtenerlo en el filtro de la siguiente manera:
private String pathToBeIgnored;
public void init(FilterConfig config) {
pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}
Si el filtro es parte de API de terceros y por lo tanto no puedes modificarlo, entonces mapea en un url-pattern
más específico, por ejemplo /otherfilterpath/*
y crea un nuevo filtro en /*
que lo reenvía a la ruta que coincide con el 3er. filtro de fiesta
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response); // Just continue chain.
} else {
request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response);
}
Para evitar que este filtro se llame a sí mismo en un bucle infinito, debe permitir que escuche (despache) REQUEST
y el filtro de terceros solo FORWARD
.
Ver también:
La aplicación de servlet no admite la característica de exclusión de forma predeterminada, sin embargo, puede hacerlo programáticamente:
- Simplemente defina un parámetro personalizado como init-param en web.xml , llámelo excluidoUrls
- Lea el parámetro dentro del método init () de su filtro y llene su valor a un campo personalizado.
- En el método dofilter () , compruebe si la url de contexto de la solicitud existe en la lista de excluidos y simplemente avance en la cadena.
Esta publicación: cómo excluir una URL de un filtro explica en detalle el enfoque y proporciona ejemplos para personalizar filtros personalizados y de terceros.
No creo que puedas, la única otra alternativa de configuración es enumerar las rutas que quieres que se filtren, así que en lugar de /*
podrías agregar algo para /this/*
y /that/*
etc., pero eso ganó '' Llevar a una solución suficiente cuando tienes muchos de esos caminos.
Lo que puede hacer es agregar un parámetro al filtro que proporcione una expresión (como una expresión regular) que se usa para omitir la funcionalidad del filtro para las rutas coincidentes. El contenedor de servlets seguirá llamando a su filtro para esas URL, pero tendrá un mejor control sobre la configuración.
Editar
Ahora que mencionas que no tienes control sobre el filtro, lo que podrías hacer es heredar de ese filtro los llamados super
métodos en sus métodos, excepto cuando la ruta url que deseas omitir esté presente y seguir la cadena de filtros como @BalusC propuesta, o crea un filtro que ejemplifica tu filtro y delega en las mismas circunstancias. En ambos casos, los parámetros de filtro incluirían tanto el parámetro de expresión que agregue como los del filtro heredado o al que delegue.
La ventaja de crear un filtro de delegación (un contenedor) es que puede agregar la clase de filtro del filtro ajustado como parámetro y reutilizarlo en otras situaciones como esta.
Si por alguna razón no puede cambiar la asignación de filtro original ("/ *" en mi caso) y está enviando a un filtro de terceros inmutable, puede encontrar útil lo siguiente:
- Interceptar el camino a ser pasado por alto
- Salte y ejecute el último anillo de la cadena de filtro (el servlet mismo)
- La omisión se realiza por reflexión, inspeccionando las instancias del contenedor en modo de depuración
Los siguientes trabajos 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(); } } }
También tuve que filtrar en función del patrón de URL (/ {servicename} / api / stats /) en código Java.
if (path.startsWith("/{servicename}/api/statistics/")) {
validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token"));
filterChain.doFilter(request, response);
}
Pero es extraño, ese servlet no es compatible con el patrón de URL que no sea (/ *), ¡Esto debería ser un caso muy común para las API de servlet!
Utilicé un enfoque descrito por Eric Daugherty : Creé un servlet especial que siempre responde con código 403 y coloca su mapeo antes que el general.
Fragmento de mapeo:
<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>
Y la clase 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);
}
}