¿Cómo agregar una clase de filtro en Spring Boot?

229

Me pregunto si hay alguna anotación para una Filterclase (para aplicaciones web) en Spring Boot. Tal vez @Filter?

Quiero agregar un filtro personalizado en mi proyecto.

La Guía de referencia de Spring Boot mencionó FilterRegistrationBean, pero no estoy seguro de cómo usarla.

janetsmith
fuente
Tenga en cuenta que el filtro agregado con @WebFilter no se comporta como un filtro real en la especificación de Servlet. Será un bean spring llamado después de muchos otros beans spring y no como filtros reales antes de cualquier código de servlet.
lrxw
¿Puedes decirme tu requerimiento exacto? Si desea clases de filtro para ComponentScan, entonces hay una anotación para ese "@ ComponentScan.Filter"
Keaz

Respuestas:

159

Si desea configurar un filtro de terceros, puede usarlo FilterRegistrationBean. Por ejemplo, el equivalente de web.xml

<filter>
     <filter-name>SomeFilter</filter-name>
        <filter-class>com.somecompany.SomeFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SomeFilter</filter-name>
    <url-pattern>/url/*</url-pattern>
    <init-param>
       <param-name>paramName</param-name>
       <param-value>paramValue</param-value>
    </init-param>
</filter-mapping>

Estos serán los dos frijoles en su @Configurationarchivo

@Bean
public FilterRegistrationBean someFilterRegistration() {

    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(someFilter());
    registration.addUrlPatterns("/url/*");
    registration.addInitParameter("paramName", "paramValue");
    registration.setName("someFilter");
    registration.setOrder(1);
    return registration;
} 

public Filter someFilter() {
    return new SomeFilter();
}

Lo anterior se probó con spring-boot 1.2.3

Haim Raman
fuente
1
¿Qué pasa si quiero agregar varios filtros? @Opal
verystrongjoe
8
Solo agregue un @Bean public FilterRegistrationBean adicionalesFilterRegistration () adicional
Haim Raman
¿Cómo se sabe el orden en que se aplican los filtros?
BeepDog
77
FilterRegistrationBean.setOrder
Haim Raman
No necesita bean de filtro cuando llama al método someFilter()directamente.
wst
117

Aquí hay un ejemplo de un método para incluir un filtro personalizado en una aplicación Spring Boot MVC. Asegúrese de incluir el paquete en un escaneo de componentes:

package com.dearheart.gtsc.filters;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Component
public class XClacksOverhead implements Filter {

  public static final String X_CLACKS_OVERHEAD = "X-Clacks-Overhead";

  @Override
  public void doFilter(ServletRequest req, ServletResponse res,
      FilterChain chain) throws IOException, ServletException {

    HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader(X_CLACKS_OVERHEAD, "GNU Terry Pratchett");
    chain.doFilter(req, res);
  }

  @Override
  public void destroy() {}

  @Override
  public void init(FilterConfig arg0) throws ServletException {}

}
tegatai
fuente
44
¿Se debe registrar el filtro en alguna parte?
gstackoverflow
1
Cuando probé ese enfoque, Filter se creó como bean e incluso se inyectó en otra clase, pero el método init () no se ejecutó . Probablemente, init () funciona solo en el registro 'normal' no por contenedor de resorte. Creo que uno puede usar PostConstruct en lugar de init () pero no lo intenté porque me negué a declarar Filter como Spring bean.
Baurzhan
¿Qué pasa con la ordenación de filtros con este enfoque?
Pavel Vlasov
¿Cómo podemos obtener el cuerpo RS de ServletResponse?
user2602807
1
Una cosa importante a tener en cuenta es que el nombre de su bean (basado en el nombre de su clase) no debe ser el mismo que un bean Spring. Por ejemplo, puede sentirse tentado a crear un MetricsFilter, pero este bean será eclipsado por el bean actuador Spring del mismo nombre. Aprendido de la manera difícil ...
kinbiko
78

No hay una anotación especial para denotar un filtro de servlet. Simplemente declaras un @Beantipo Filter(o FilterRegistrationBean). Un ejemplo (agregar un encabezado personalizado a todas las respuestas) está en el propio EndpointWebMvcAutoConfiguration de Boot ;

Si solo declara un Filter, se aplicará a todas las solicitudes. Si también agrega un, FilterRegistrationBeantambién puede especificar servlets individuales y patrones de URL para aplicar.

Nota:

A partir de Spring Boot 1.4, FilterRegistrationBeanno está en desuso y simplemente movió paquetes de org.springframework.boot.context.embedded.FilterRegistrationBeanaorg.springframework.boot.web.servlet.FilterRegistrationBean

Dave Syer
fuente
¿Te importaría decirme cómo incluir la entrada correspondiente en build.gradle? Agregué lo siguiente, pero no se compiló: provideCompile ('javax.servlet: servlet-api: 2.5') runtime ('javax.servlet: jstl: 1.1.2')
janetsmith
2
Spring Boot no funcionará con Servlet 2.5, y todavía no hay mucho soporte para JSP. Realmente no soy un graduado, así que no sé qué estás tratando de hacer. ¿Qué tiene de malo "compilar"? ¿Funciona si solo depende de "spring-boot-starter-web"? (Sin embargo, no creo que estas preguntas estén relacionadas con la pregunta original, así que ¿quizás debería publicar nuevamente con las nuevas preguntas?)
Dave Syer,
Agregué un filtro implementando la interfaz de filtro, sin embargo, Eclipse no puede encontrar la interfaz. Así que estoy tratando de descubrir cómo agregarlo a classpath para compilarlo.
janetsmith
1
Sí, por supuesto que necesitas tener Filteren tu classpath. Normalmente, solo usaría el spring-boot-starter-webpara extraer todas las descripciones relevantes (por ejemplo, aquí ).
Dave Syer
Como detallan otras respuestas, también puede anotar su clase de filtro con @Component y se registrará automáticamente (para todas las URL).
Jakub Holý
72

Hay tres formas de agregar su filtro,

  1. Anote su filtro con uno de los estereotipos de Spring como @Component
  2. Registre un @Beancon Filtertipo en Spring@Configuration
  3. Registre un @Beancon FilterRegistrationBeantipo en Spring@Configuration

El n. ° 1 o el n. ° 2 servirán si desea que su filtro se aplique a todas las solicitudes sin personalización; de lo contrario, use el n. ° 3. No necesita especificar la exploración de componentes para que el n. ° 1 funcione siempre y cuando coloque su clase de filtro en el mismo o subpaquete de su SpringApplicationclase. Para el n. ° 3, el uso junto con el n. ° 2 solo es necesario cuando desea que Spring administre su clase de filtro, como tener dependencias cableadas automáticamente. Funciona bien para mí el nuevo filtro que no necesita ninguna conexión automática / inyección de dependencia.

Aunque combinar # 2 y # 3 funciona bien, me sorprendió que no termine con dos filtros que se aplican dos veces. Supongo que Spring combina los dos beans como uno solo cuando llama al mismo método para crearlos. En caso de que quiera usar el n. ° 3 solo con el autoconexión, puede hacerlo AutowireCapableBeanFactory. Lo siguiente es un ejemplo,

private @Autowired AutowireCapableBeanFactory beanFactory;

    @Bean
    public FilterRegistrationBean myFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        Filter myFilter = new MyFilter();
        beanFactory.autowireBean(myFilter);
        registration.setFilter(myFilter);
        registration.addUrlPatterns("/myfilterpath/*");
        return registration;
    }
barryku
fuente
Excelente respuesta Gracias por detallar todas las opciones y también por cubrir cómo conectar automáticamente el cable Filtermientras se usaFilterRegistrationBean
sbk
Gran respuesta. ¡Esto es exactamente lo que he ganado!
haykart
Esto también se describe aquí: baeldung.com/spring-boot-add-filter
Jakub Holý
31

ACTUALIZACIÓN: 2017-12-16:

Hay 2 formas simples de hacer esto en Spring Boot 1.5.8. LIBERACIÓN, sin necesidad de XML.

Primera forma: si no tiene ningún patrón de URL específico, puede usar @Component así: (El código completo y los detalles están aquí https://www.surasint.com/spring-boot-filter/ )

@Component
public class ExampleFilter implements Filter{
   ...
}

Segunda forma: si desea usar patrones de URL, puede usar @WebFilter de esta manera: (El código completo y los detalles están aquí https://www.surasint.com/spring-boot-filter-urlpattern/ )

@WebFilter(urlPatterns = "/api/count")
public class ExampleFilter implements Filter{
 ...
}

Pero también debe agregar la anotación @ServletComponentScan en su clase @SpringBootApplication:

@ServletComponentScan
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
...
}

Tenga en cuenta que @Component es la anotación de Spring, pero @WebFilter no lo es. @WebFilter es la anotación Servlet 3.

En ambos sentidos, solo necesita una dependencia básica de Spring Boot en pom.xml (no es necesario un jasper incrustado de tomcat explícito)

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
    </parent>

    <groupId>com.surasint.example</groupId>
    <artifactId>spring-boot-04</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

ADVERTENCIA: La primera forma, si el Controlador en Spring Boot vuelve a un archivo JSP, la solicitud pasará el filtro dos veces.

Mientras que, en la segunda forma, la solicitud pasará el filtro solo una vez.

Prefiero la segunda forma porque es más similar al comportamiento predeterminado en la especificación de Servlet ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html )

Puede ver más registros de prueba aquí https://www.surasint.com/spring-boot-webfilter-instead-of-component/

Surasin Tancharoen
fuente
He visto Filterque se llama a la interfaz varias veces durante el lanzamiento de la aplicaciónContext. ¿Hay alguna forma de ejecutarlo solo una vez?
Pra_A
@PAA ¿te refieres a mis ejemplos?
Surasin Tancharoen
20

Aquí hay un ejemplo de mi clase de filtro personalizada:

package com.dawson.controller.filter;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@Component
public class DawsonApiFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        if (req.getHeader("x-dawson-nonce") == null || req.getHeader("x-dawson-signature") == null) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setContentType("application/json");
            httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "Required headers not specified in the request");
            return;
        }
        chain.doFilter(request, response);
    }
}

Y lo agregué a la configuración de arranque de Spring agregándolo a la clase de Configuración de la siguiente manera:

package com.dawson.configuration;

import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import com.dawson.controller.filter.DawsonApiFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@SpringBootApplication
public class ApplicationConfiguration {
    @Bean
    public FilterRegistrationBean dawsonApiFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new DawsonApiFilter());
// In case you want the filter to apply to specific URL patterns only
        registration.addUrlPatterns("/dawson/*");
        return registration;
    }
}
DPancs
fuente
14

De Spring docs,

Contenedores de servlets integrados: agregue un servlet, filtro o escucha a una aplicación

Para agregar un Servlet, Filtro o Servlet * Listener, proporcione una definición @Bean para él.

P.ej:

@Bean
public Filter compressFilter() {
    CompressingFilter compressFilter = new CompressingFilter();
    return compressFilter;
}

Agregue esta @Beanconfiguración a su @Configurationclase y el filtro se registrará al inicio.

También puede agregar servlets, filtros y oyentes utilizando el escaneo classpath,

Las clases anotadas @WebServlet, @WebFilter y @WebListener se pueden registrar automáticamente con un contenedor de servlets incrustado anotando una clase @Configuration con @ServletComponentScan y especificando los paquetes que contienen los componentes que desea registrar. Por defecto, @ServletComponentScan escaneará desde el paquete de la clase anotada.

Suerte
fuente
7

Si usa Spring Boot + Spring Security, puede hacerlo en la configuración de seguridad.

En el siguiente ejemplo, estoy agregando un filtro personalizado antes del UsernamePasswordAuthenticationFilter (ver todos los filtros predeterminados de Spring Security y su orden ).

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .addFilterBefore(
                new MyFilter(filterDependency),
                UsernamePasswordAuthenticationFilter.class);
    }
}

Y la clase de filtro

class MyFilter extends OncePerRequestFilter  {
    private final FilterDependency filterDependency;

    public MyFilter(FilterDependency filterDependency) {
        this.filterDependency = filterDependency;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
        HttpServletResponse response,
        FilterChain filterChain)
        throws ServletException, IOException {
       // filter
       filterChain.doFilter(request, response);
    }
}
Andrei Epure
fuente
5

Usando la anotación @WebFilter, se puede hacer de la siguiente manera:

@WebFilter(urlPatterns = {"/*" })
public class AuthenticationFilter implements Filter{

    private static Logger logger = Logger.getLogger(AuthenticationFilter.class);

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

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

         logger.info("checking client id in filter");
        HttpServletRequest request = (HttpServletRequest) arg0;
        String clientId = request.getHeader("clientId");
        if (StringUtils.isNotEmpty(clientId)) {
            chain.doFilter(request, response);
        } else {
            logger.error("client id missing.");
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}
KayV
fuente
3
También agregue @ServletComponentScan
Justas
5

Tenemos aproximadamente cuatro opciones diferentes para registrar un filtro usando Spring .

En primer lugar, podemos crear un filtro de implementación de Spring Bean o extender HttpFilter :

@Component
public class MyFilter extends HttpFilter {

    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
        // Implementation details...

        chain.doFilter(request, response);
    }
}

En segundo lugar, podemos crear un bean Spring extendiendo GenericFilterBean :

@Component
public class MyFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
  throws IOException, ServletException {
    //Implementation details...

        chain.doFilter(currentRequest, servletResponse);
    }
}

Alternativamente, podemos usar la clase FilterRegistrationBean :

@Configuration
public class FilterConfiguration {

    private final MyFilter myFilter;

    @Autowired
    public FilterConfiguration(MyFilter myFilter) {
        this.myFilter = myFilter;
    }

    @Bean
    public FilterRegistrationBean<MyFilter> myFilterRegistration() {
        FilterRegistrationBean<DateLoggingFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(myFilter);
        filterRegistrationBean.setUrlPatterns(Collections.singletonList("/*"));
        filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST);
        filterRegistrationBean.setOrder(Ordered.LOWEST_PRECEDENCE - 1);
        return filterRegistrationBean;
    }
}

Y, por último, podemos utilizar el @WebFilter anotación con @ServletComponentScan :

@WebFilter(urlPatterns = "/*", dispatcherTypes = {DispatcherType.REQUEST})
public class MyFilter extends HttpFilter {

    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
  throws IOException, ServletException {
        // Implementation details...

        chain.doFilter(request, response);
    }
}
isaolmez
fuente
¿Qué filtro usar y por qué?
Pra_A
3

Es más un consejo que una respuesta, pero si está utilizando un Spring MVC en su aplicación web, la buena idea es utilizar Spring HandlerInterceptor en lugar de Filter

Puede hacer el mismo trabajo, pero también - Puede trabajar con ModelAndView - Sus métodos pueden llamarse antes y después del procesamiento de la solicitud, o después de la finalización de la solicitud.
- Se puede probar fácilmente

1 Implemente la interfaz HandlerInterceptor y agregue una anotación @Component a su clase

@Component
public class SecurityInterceptor implements HandlerInterceptor {

    private static Logger log = LoggerFactory.getLogger(SecurityInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        request.getSession(true);
        if(isLoggedIn(request))
            return true;

        response.getWriter().write("{\"loggedIn\":false}");
        return false;
    }

    private boolean isLoggedIn(HttpServletRequest request) {
        try {
            UserSession userSession = (UserSession) request.getSession(true).getAttribute("userSession");
            return userSession != null && userSession.isLoggedIn();
        } catch(IllegalStateException ex) {
            return false;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {

    }
}

2 Configure su interceptor

@Configuration
public class WebConfig implements WebMvcConfigurer {

    private HandlerInterceptor securityInterceptor;

    @Autowired
    public void setSecurityInterceptor(HandlerInterceptor securityInterceptor) {
        this.securityInterceptor = securityInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(securityInterceptor).addPathPatterns("/**").excludePathPatterns("/login", "/logout");
    }

}
Vasily Komarov
fuente
Simple y elegante! Gracias
MrMins
3

Este filtro también lo ayudará a permitir el acceso de origen cruzado

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

            HttpServletResponse response = (HttpServletResponse) res;
            HttpServletRequest request = (HttpServletRequest) req;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "20000");
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN");

            if("OPTIONS".equalsIgnoreCase(request.getMethod())) {
                response.setStatus(HttpServletResponse.SC_OK);
            } else {
                chain.doFilter(req, res);
            }
    }


    public void destroy() {}

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}
Ghulam Murtaza
fuente
2

Puede usar @WebFilter javax.servlet.annotation.WebFilter en una clase que implemente javax.servlet.Filter

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {}

Luego use @ServletComponentScan para registrarse

Cwrwhaf
fuente
2

Vi muchas respuestas aquí pero no probé ninguna de ellas. Acabo de crear el filtro como en el siguiente código.

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/Admin")
@Configuration
public class AdminFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse  servletResponse, FilterChain filterChain) throws IOException, ServletException      {
    System.out.println("happened");

    }

    @Override
    public void destroy() {

    }
}

Y dejó la aplicación Spring Boot restante tal como estaba.

Shaaban Ebrahim
fuente
2

Necesita 2 cosas principales: - Agregar @ServletComponentScana su clase principal: puede agregar un paquete llamado filtro dentro de él, crear una Filterclase que tenga lo siguiente:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestFilter implements Filter {

 // whatever field you have

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
    HttpServletResponse response = (HttpServletResponse) res;
    HttpServletRequest request = (HttpServletRequest) req;

 // whatever implementation you want

        try {
            chain.doFilter(req, res);
        } catch(Exception e) {
            e.printStackTrace();
        }

}

public void init(FilterConfig filterConfig) {}

public void destroy() {}
}
Slimane Deb
fuente
1

También puede hacer un filtro utilizando @WebFilter e implementa Filter, lo hará.

 @Configuration
        public class AppInConfig 
        {
        @Bean
      @Order(1)
      public FilterRegistrationBean aiFilterRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new TrackingFilter());
            registration.addUrlPatterns("/**");
            registration.setOrder(1);
            return registration;
        } 
    @Bean(name = "TrackingFilter")
        public Filter TrackingFilter() {
            return new TrackingFilter();
        }   
    }
Muni
fuente
1

Los filtros, como su nombre indica, se utilizan para realizar el filtrado en la solicitud a un recurso o en la respuesta de un recurso, o en ambos. Spring Boot ofrece pocas opciones para registrar filtros personalizados en la aplicación Spring Boot. Veamos las diferentes opciones.

1. Definir filtro de arranque de resorte y orden de invocación

Implemente la interfaz de filtro para crear un nuevo filtro en Spring Boot.

@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {

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

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  LOGGER.info("########## Initiating Custom filter ##########");
 }

 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

  HttpServletRequest request = (HttpServletRequest) servletRequest;
  HttpServletResponse response = (HttpServletResponse) servletResponse;

  LOGGER.info("Logging Request  {} : {}", request.getMethod(), request.getRequestURI());

  //call next filter in the filter chain
  filterChain.doFilter(request, response);

  LOGGER.info("Logging Response :{}", response.getContentType());
 }

 @Override
 public void destroy() {
  // TODO: 7/4/18
 }
}

Veamos rápidamente algunos puntos importantes en el código anterior.

  • El filtro registrado por la anotación @Component .
  • Para disparar filtros en el orden correcto, necesitábamos usar la anotación @Order .

    @Component
    @Order(1)
    public class CustomFirstFilter implements Filter {
    
    }
    @Component
    @Order(2)
    public class CustomSecondFilter implements Filter {
    
    }

En el código anterior, CustomFirstFilter se ejecutará antes que CustomSecondFilter.

Cuanto menor es el número, mayor es la precedencia

2. Patrón de URL

Si el mapeo basado en convenciones no es lo suficientemente flexible, podemos usar FilterRegistrationBean para el control completo de la aplicación. Aquí, no use la anotación @Component para la clase de filtro, pero registre el filtro usando un FilterRegistrationBean .

 public class CustomURLFilter implements Filter {

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

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  LOGGER.info("########## Initiating CustomURLFilter filter ##########");
 }

 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

  HttpServletRequest request = (HttpServletRequest) servletRequest;
  HttpServletResponse response = (HttpServletResponse) servletResponse;

  LOGGER.info("This Filter is only called when request is mapped for /customer resource");

  //call next filter in the filter chain
  filterChain.doFilter(request, response);
 }

 @Override
 public void destroy() {

 }
}

Registre el filtro personalizado con FilterRegistrationBean .

@Configuration
public class AppConfig {

 @Bean
 public FilterRegistrationBean < CustomURLFilter > filterRegistrationBean() {
  FilterRegistrationBean < CustomURLFilter > registrationBean = new FilterRegistrationBean();
  CustomURLFilter customURLFilter = new CustomURLFilter();

  registrationBean.setFilter(customURLFilter);
  registrationBean.addUrlPatterns("/greeting/*");
  registrationBean.setOrder(2); //set precedence
  return registrationBean;
 }
}
Yogesh
fuente
1

    @WebFilter(urlPatterns="/*")
    public class XSSFilter implements Filter {

        private static final org.apache.log4j.Logger LOGGER = LogManager.getLogger(XSSFilter.class);

        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            LOGGER.info("Initiating XSSFilter... ");

        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpRequestWrapper requestWrapper = new HttpRequestWrapper(req);
            chain.doFilter(requestWrapper, response);
        }

        @Override
        public void destroy() {
            LOGGER.info("Destroying XSSFilter... ");
        }

    }

Debe implementar Filter y debe anotarse con @WebFilter (urlPatterns = "/ *")

Y en la clase Aplicación o Configuración, debe agregar @ServletComponentScan. De este modo, su filtro se registrará.

Rahul Anand
fuente
Esto @WebFilteres solo desde Servlet 3.0. Por lo tanto, podría no funcionar correctamente para 2.5
ha9u63ar
1

Paso 1: Cree un componente de filtro implementando la interfaz de filtro.

@Component
public class PerformanceFilter implements Filter {

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

            ......
            ......
    }

}

Paso 2: establezca este filtro en los patrones de uri utilizando FilterRegistrationBean.

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<PerformanceFilter> perfFilter() {
        FilterRegistrationBean<PerformanceFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new PerformanceFilter());
        registration.addUrlPatterns("/*");
        return registration;
    }
}

Puede consultar este enlace para completar la solicitud.

Hari Krishna
fuente
0

Primero, agregue @ServletComponentScana su clase SpringBootApplication.

@ServletComponentScan
public class Application {

En segundo lugar, cree un archivo de filtro que extienda el filtro o la clase de filtro de terceros y agréguelo @WebFiltera este archivo de esta manera:

@Order(1) //optional
@WebFilter(filterName = "XXXFilter", urlPatterns = "/*",
    dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD},
    initParams = {@WebInitParam(name = "confPath", value = "classpath:/xxx.xml")})
public class XXXFilter extends Filter{
oaoit
fuente
0

Vi la respuesta de @Vasily Komarov. Enfoque similar, pero usando la clase abstracta HandlerInterceptorAdapter en lugar de usar HandlerInterceptor .

Aquí hay un ejemplo...

@Component
public class CustomInterceptor extends HandlerInterceptorAdapter {
   @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }
}

@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private CustomInterceptor customInterceptor ;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(customInterceptor );
    }

}
Shaunak Patel
fuente
0

Como todos saben, Spring Boot es una forma maravillosa de desarrollar una aplicación web o una aplicación independiente con una configuración mínima y una configuración obstinada.

Así es como he logrado un desarrollo de filtro web en la aplicación Spring Boot

Mis especificaciones SpringBootApp: -

Versión de Spring Boot: 2.0.4.RELEASE
Versión de Java: 8.0
Especificación del servlet: Servlet 3.0 (obligatorio e importante)

Declaré mi filtro web de la siguiente manera, cumpliendo con las especificaciones de Servlet 3.0

ingrese la descripción de la imagen aquí Esta es la forma programática de definir un filtro como reemplazo de las definiciones basadas en web.xml.

La anotación "@Webfilter" será procesada por el contenedor durante la implementación, la clase Filter en la que se encuentra se creará según la configuración y se aplicará a los patrones de URL, javax.servlet.Servlets y javax.servlet.DispatcherTypes.

Para evitar completamente Web.xml y lograr una aplicación web "desplegable": -

Para implementar Spring Boot Application como "WAR tradicional", la clase de aplicación debe extender SpringBootServletInitializer.

NOTA :: SpringBootServletInitializer es una "Implementación programática" de web.xml con referencia a las especificaciones de Servlet 3.0+, que requiere una implementación de WebApplicationInitializer.

Por lo tanto, SpringBootApplication no requiere "web.xml" como su clase de aplicación (después de extender SpringBootServletInitializer) escanea para
- @WebFilter,
- @WebListener y
- @WebServlet.

Anotación @ServletComponentScan

Esta anotación permite escanear paquetes base para los componentes web anotados con @WebFilter, @WebListener y @WebServlet.

Debido al hecho de que los contenedores integrados no son compatibles con las anotaciones @WebServlet, @WebFilter y @WebListener, Spring Boot, confiando en gran medida en los contenedores integrados, introdujo esta nueva anotación @ServletComponentScan para admitir algunos frascos dependientes que usan estas 3 anotaciones.

El escaneo solo se realiza cuando se utiliza un contenedor de Servlet incorporado.

La siguiente es mi definición de clase de aplicación Spring Boot: -

ingrese la descripción de la imagen aquí

Inicializador de servlet personalizado: -

Aquí: he definido una clase personalizada: "ServletInitializer" que amplía la clase: SpringBootServletInitializer.

Como se explicó anteriormente, SpringBootServletInitializer es responsable de escanear anotaciones: -
- @WebFilter,
- @WebListener y
- @WebServlet.

Y, por lo tanto, la clase de aplicación Spring Boot debería

  • Extienda la clase: SpringBootServletInitializer O
  • extend Clase personalizada que extiende la clase: SpringBootServletInitializer

ingrese la descripción de la imagen aquí

Philip Dilip
fuente
-6

Los filtros se utilizan principalmente en los archivos de registro; varía según el registrador que utilice en el proyecto que Lemme explica para log4j2:

<Filters>
                <!-- It prevents error -->
                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
                <!-- It prevents debug -->
                <ThresholdFilter level="debug" onMatch="DENY" onMismatch="NEUTRAL" />
                <!-- It allows all levels except debug/trace -->
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" /> 
            </Filters>

Los filtros se usan para restringir los datos y utilicé el filtro de umbral aún más para restringir los niveles de datos en el flujo. Mencioné los niveles que pueden restringirse allí. Para más información, consulte el orden de nivel de log4j2 - Log4J Levels: ALL> TRACE> DEBUG> INFO> WARN> ERROR> FATAL> OFF

saravanan
fuente
FilterRegistrationBeancomo se menciona en la pregunta se hace para javax.servlet.Filter, esta respuesta habla deorg.apache.logging.log4j.core.Filter
Steve Buzonas