Como adicionar uma classe de filtro no Spring Boot?

229

Gostaria de saber se existe alguma anotação para uma Filterclasse (para aplicativos da Web) no Spring Boot? Talvez @Filter?

Quero adicionar um filtro personalizado ao meu projeto.

O Guia de Referência do Spring Boot mencionado sobre FilterRegistrationBean, mas não sei como usá-lo.

janetsmith
fonte
Observe que o filtro adicionado ao @WebFilter não se comporta como um filtro real nas especificações do Servlet. Será um spring bean chamado após muitos outros spring beans e não como filtros reais antes de qualquer código de servlet.
lrxw
você pode me dizer sua exigência exata. Se você quiser classes de filtro para ComponentScan então há uma anotação para isso "@ ComponentScan.Filter"
Keaz

Respostas:

159

Se você deseja configurar um filtro de terceiros, pode usar FilterRegistrationBean. Por exemplo, o equivalente a 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>

Esses serão os dois beans no seu @Configurationarquivo

@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();
}

O acima foi testado com boot de mola 1.2.3

Haim Raman
fonte
1
e se eu quiser adicionar vários filtros? @Opal
verystrongjoe
8
Basta adicionar um @Bean public FilterRegistrationBean adicionalFilterRegistration ()
Haim Raman
Como se sabe a ordem em que os filtros são aplicados?
BeepDog
7
FilterRegistrationBean.setOrder
Haim Raman
Você não precisa do bean de filtro quando chama o método someFilter()diretamente.
wst 14/03/19
117

Aqui está um exemplo de um método de inclusão de um filtro personalizado em um aplicativo Spring Boot MVC. Certifique-se de incluir o pacote em uma verificação de componente:

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
fonte
4
O filtro deve ser registrado em algum lugar?
gstackoverflow
1
Quando tentei essa abordagem, o Filter foi criado como bean e foi injetado em outra classe, mas o método init () não foi executado . Provavelmente, init () funciona apenas no registro 'normal', não no contêiner de mola. Eu acho que alguém pode usar PostConstruct em vez de init (), mas não tentei isso porque me recusei a declarar Filter como Spring bean.
Baurzhan
E quanto à solicitação de filtros usando essa abordagem?
Pavel Vlasov 08/09
Como podemos obter o corpo de RS do ServletResponse?
user2602807
1
Uma coisa importante a ser observada é que o nome do seu bean (com base no nome da sua classe) não deve ser o mesmo que um Spring bean. Por exemplo, você pode ser tentado a criar um MetricsFilter, mas esse bean será ofuscado pelo bean do atuador Spring com o mesmo nome. Aprendi isso da maneira mais difícil ...
kinbiko
78

Não há uma anotação especial para indicar um filtro de servlet. Você acabou de declarar um @Beando tipo Filter(ou FilterRegistrationBean). Um exemplo (adicionando um cabeçalho personalizado a todas as respostas) está no próprio EndpointWebMvcAutoConfiguration do Boot ;

Se você declarar apenas um Filter, será aplicado a todos os pedidos. Se você também adicionar um, FilterRegistrationBeanpoderá especificar adicionalmente servlets e padrões de URL a serem aplicados.

Nota:

A partir do Spring Boot 1.4, FilterRegistrationBeannão é preterido e simplesmente move os pacotes de org.springframework.boot.context.embedded.FilterRegistrationBeanparaorg.springframework.boot.web.servlet.FilterRegistrationBean

Dave Syer
fonte
Você gostaria de me dizer como incluir a entrada correspondente no build.gradle? Eu adicionei o seguinte, mas ele não é compilado: runtimeComputed ('javax.servlet: servlet-api: 2.5') ('javax.servlet: jstl: 1.1.2')
janetsmith
2
O Spring Boot não funcionará com o Servlet 2.5 e ainda não há muito suporte para JSP. Eu não sou realmente uma niveladora, então não sei o que você está tentando fazer. O que há de errado com "compilar"? Funciona se você depender apenas de "spring-boot-starter-web"? (Eu não acho que estas questões estão relacionadas à pergunta inicial, porém, talvez por isso você deve postar novamente com as novas perguntas?)
Dave Syer
Eu adicionei um filtro implementando a interface Filter, no entanto, o Eclipse não consegue encontrar a interface. Então, eu estou tentando descobrir como adicioná-lo ao caminho de classe para compilar.
janetsmith
1
Sim, é claro que você precisa ter Filterno seu caminho de classe. Normalmente, eu apenas usaria o spring-boot-starter-webpara obter todas as dependências relevantes (por exemplo, aqui ).
Dave Syer
Como outros detalhes das respostas, você também pode apenas anotar sua classe Filter com @Component e ela será registrada automaticamente (para todos os URLs).
Jakub Holý
72

Existem três maneiras de adicionar seu filtro,

  1. Anote seu filtro com um dos estereótipos do Spring, como @Component
  2. Registre um @Beancom Filtertipo no Spring@Configuration
  3. Registre um @Beancom FilterRegistrationBeantipo no Spring@Configuration

O número 1 ou o número 2 funcionará se você desejar que o filtro se aplique a todos os pedidos sem personalização; use o número 3 caso contrário. Você não precisa especificar a varredura de componentes para que o número 1 funcione, desde que você coloque sua classe de filtro no mesmo ou subpacote de sua SpringApplicationclasse. Para o número 3, o uso juntamente com o número 2 é necessário apenas quando você deseja que o Spring gerencie sua classe de filtro, como dependências automáticas. Funciona muito bem para eu colocar meu novo filtro, que não precisa de nenhuma dependência / injeção automática.

Embora a combinação de # 2 e # 3 funcione bem, fiquei surpreso por não ter dois filtros aplicados duas vezes. Meu palpite é que o Spring combina os dois beans como um quando chama o mesmo método para criar os dois. Caso você queira usar o nº 3 sozinho com a autenticação automática, você pode AutowireCapableBeanFactory. A seguir está um exemplo,

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
fonte
Excelente resposta. Obrigado por detalhando todas as opções e também cobrindo como autowire seu Filterdurante o usoFilterRegistrationBean
SBK
Ótima resposta. Isso é exatamente o que eu costumava !!
haykart
Isso também é descrito aqui: baeldung.com/spring-boot-add-filter
Jakub Holý
31

ATUALIZAÇÃO: 16-12-2017:

Existem 2 maneiras simples de fazer isso no Spring Boot 1.5.8.RELEASE, sem necessidade de XML.

Primeira maneira: se você não possui um padrão de URL específico, pode usar o @Component assim: (Código e detalhes completos estão aqui https://www.surasint.com/spring-boot-filter/ )

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

Segunda maneira: se você deseja usar padrões de URL, pode usar o @WebFilter assim: (Código e detalhes completos estão aqui https://www.surasint.com/spring-boot-filter-urlpattern/ )

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

Mas você também precisa adicionar a anotação @ServletComponentScan na sua classe @SpringBootApplication:

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

Observe que @Component é a anotação do Spring, mas @WebFilter não. O @WebFilter é uma anotação do Servlet 3.

Nos dois sentidos, você só precisa da dependência básica do Spring Boot no pom.xml (não é necessário jasper incorporado explícito do tomcat)

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

AVISO: A primeira maneira, se o Controlador no Spring Boot retornar para um arquivo JSP, a solicitação passará o filtro duas vezes.

Enquanto, na segunda maneira, a solicitação passará no filtro apenas uma vez.

Prefiro a segunda maneira, porque é mais semelhante ao comportamento padrão na especificação de Servlet ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html )

Você pode ver mais registros de teste aqui https://www.surasint.com/spring-boot-webfilter-instead-of-component/

Surasin Tancharoen
fonte
Eu já vi Filterinterface sendo chamada várias vezes durante o lançamento do applicationContext. Existe alguma maneira de executá-lo apenas uma vez?
Pra_A
@PAA você quer dizer com os meus exemplos?
Surasin Tancharoen 9/08/19
20

Aqui está um exemplo da minha classe 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);
    }
}

E eu o adicionei à configuração de inicialização do Spring adicionando-a à classe Configuration da seguinte maneira:

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

Nos documentos do Spring,

Contêineres de servlet incorporados - Adicione um servlet, filtro ou ouvinte a um aplicativo

Para adicionar um Servlet, Filtro ou Servlet *, o Listener fornece uma definição @Bean para ele.

Por exemplo:

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

Adicione essa @Beanconfiguração à sua @Configurationclasse e o filtro será registrado na inicialização.

Além disso, você pode adicionar Servlets, Filtros e Ouvintes usando a verificação de caminho de classe,

As classes anotadas @WebServlet, @WebFilter e @WebListener podem ser registradas automaticamente com um contêiner de servlet incorporado, anotando uma classe @Configuration com @ServletComponentScan e especificando os pacotes que contêm os componentes que você deseja registrar. Por padrão, o @ServletComponentScan varrerá do pacote da classe anotada.

Por sorte
fonte
7

Se você usa o Spring Boot + Spring Security, pode fazer isso na configuração de segurança.

No exemplo abaixo, estou adicionando um filtro personalizado antes do UsernamePasswordAuthenticationFilter (veja todos os filtros padrão do Spring Security e sua ordem ).

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

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

E a classe 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
fonte
5

Usando a anotação @WebFilter, isso pode ser feito da seguinte maneira:

@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
fonte
3
Adicione também @ServletComponentScan
Justas
5

Temos aproximadamente quatro opções diferentes para registrar um filtro usando o Spring .

Primeiramente, podemos criar um bean Spring implementando o Filter ou estendendo o 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);
    }
}

Em segundo lugar, podemos criar um bean Spring estendendo o 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);
    }
}

Como alternativa, podemos usar a classe 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;
    }
}

E por último, podemos usar o @WebFilter anotação com @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
fonte
Qual filtro usar e por quê?
Pra_A
3

É mais um conselho do que resposta, mas se você estiver usando um Spring MVC em seu aplicativo da web, a boa idéia é usar o Spring HandlerInterceptor em vez do Filter

Ele pode fazer o mesmo trabalho, mas também - Pode trabalhar com ModelAndView - Seus métodos podem ser chamados antes e depois do processamento da solicitação ou após a conclusão da solicitação.
- Pode ser facilmente testado

1 Implemente a interface HandlerInterceptor e adicione uma anotação @Component à sua classe

@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 seu 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
fonte
Simples e elegante! Obrigado
MrMins
3

Esse filtro também ajudará você a permitir o acesso entre origens

@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
fonte
2

Você pode usar @WebFilter javax.servlet.annotation.WebFilter em uma classe que implementa javax.servlet.Filter

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

Em seguida, use @ServletComponentScan para registrar

Cwrwhaf
fonte
2

Vi muitas respostas aqui, mas não tentei nenhuma delas. Acabei de criar o filtro como no código a seguir.

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() {

    }
}

E deixou o restante do aplicativo Spring Boot como estava.

Shaaban Ebrahim
fonte
2

Você precisa de duas coisas principais: - Adicionar @ServletComponentScanà sua classe principal - você pode adicionar um pacote chamado filter dentro dele, para criar uma Filterclasse com o seguinte:

@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
fonte
1

você também pode criar um filtro usando o @WebFilter e implementa o Filter, ele fará.

 @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
fonte
1

Filtros como o nome sugere usado para executar a filtragem na solicitação para um recurso ou na resposta de um recurso, ou em ambos. O Spring Boot fornece poucas opções para registrar filtros personalizados no aplicativo Spring Boot. Vejamos as diferentes opções.

1. Definir filtro de inicialização da primavera e ordem de chamada

Implemente a interface Filter para criar um novo filtro no 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
 }
}

Vamos examinar rapidamente alguns pontos importantes no código acima

  • O filtro registrado pela anotação @Component .
  • Para disparar filtros na ordem certa, precisamos usar a anotação @Order .

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

No código acima, CustomFirstFilter será executado antes do CustomSecondFilter.

Quanto menor o número, maior a precedência

2. Padrão de URL

Se o mapeamento baseado em convenções não for flexível o suficiente, podemos usar FilterRegistrationBean para o controle completo do aplicativo. Aqui, não use a anotação @Component para a classe filter, mas registre o filtro usando um 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 o filtro personalizado usando 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
fonte
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... ");
        }

    }

Você precisa implementar o Filter e precisa ser anotado com @WebFilter (urlPatterns = "/ *")

E na classe Aplicativo ou Configuração, você precisa adicionar @ServletComponentScan. Dessa forma, seu filtro será registrado.

Rahul Anand
fonte
Isso @WebFilterocorre apenas desde o Servlet 3.0. Portanto, ele pode não funcionar corretamente para 2.5
ha9u63ar
1

Etapa 1: Crie um componente de filtro implementando a interface Filter.

@Component
public class PerformanceFilter implements Filter {

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

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

}

Etapa 2: defina esse filtro para os padrões de URI usando FilterRegistrationBean.

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

Você pode consultar este link para obter a aplicação completa.

Hari Krishna
fonte
0

Primeiro, adicione @ServletComponentScanà sua classe SpringBootApplication.

@ServletComponentScan
public class Application {

Segundo, crie um arquivo de filtro estendendo a classe Filter ou de filtro de terceiros e adicione @WebFiltera este arquivo assim:

@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
fonte
0

Eu vi a resposta de @Vasily Komarov. Abordagem semelhante, mas usando a classe abstrata HandlerInterceptorAdapter em vez de usar HandlerInterceptor .

Aqui está um exemplo...

@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
fonte
0

Como todos sabem, o Spring Boot é uma maneira maravilhosa de desenvolver um WebApp ou StandaloneApp com configuração mínima e instalação opinativa.

Foi assim que consegui um desenvolvimento de filtro da Web no aplicativo Spring Boot

My SpringBootApp Especificações: -

Versão Spring Boot: 2.0.4.RELEASE
Versão Java: 8.0
Especificação de Servlet: Servlet 3.0 (obrigatório e importante)

Declarei meu filtro da Web da seguinte maneira, aderindo às especificações de servlet 3.0

insira a descrição da imagem aqui Essa é a maneira programática de definir um filtro como um substituto das definições baseadas no web.xml.

A anotação "@Webfilter" será processada pelo contêiner durante a implantação, a classe Filter na qual ela será encontrada será criada conforme a configuração e aplicada aos padrões de URL, javax.servlet.Servlets e javax.servlet.DispatcherTypes.

Para evitar completamente o Web.xml e obter o WebApp "Implantável": -

Para implantar o aplicativo Spring Boot como "WAR tradicional", a classe do aplicativo deve estender o SpringBootServletInitializer.

NOTA :: SpringBootServletInitializer é uma "Implementação Programática" do web.xml com referência às especificações do Servlet 3.0+, que requer uma implementação do WebApplicationInitializer.

Portanto, SpringBootApplication não requer "web.xml", pois sua classe Application (após estender o SpringBootServletInitializer) procura
- @WebFilter,
- @WebListener e
- @WebServlet.

Anotação @ServletComponentScan

Esta anotação permite a varredura de pacotes base para os componentes da web anotados com @WebFilter, @WebListener e @WebServlet.

Como os contêineres incorporados não suportam as anotações @WebServlet, @WebFilter e @WebListener, o Spring Boot, contando bastante com os contêineres incorporados, apresentou esta nova anotação @ServletComponentScan para suportar alguns jars dependentes que usam essas três anotações.

A digitalização é realizada apenas ao usar um contêiner Servlet incorporado.

A seguir está a minha definição de classe de aplicativo de inicialização Spring: -

insira a descrição da imagem aqui

Inicializador de servlet personalizado: -

Aqui: eu defini uma classe personalizada: "ServletInitializer" que estende a classe: SpringBootServletInitializer.

Conforme explicado anteriormente, o SpringBootServletInitializer é responsável pela verificação das anotações: -
- @WebFilter,
- @WebListener e
- @WebServlet.

E, portanto, a classe de aplicativo Spring Boot deve

  • Estenda a classe: SpringBootServletInitializer OU
  • estender Classe personalizada que estende a classe: SpringBootServletInitializer

insira a descrição da imagem aqui

Philip Dilip
fonte
-6

Os filtros são usados ​​principalmente nos arquivos do criador de logs, varia de acordo com o criador de logs que você está usando no projeto Lemme Explicate 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>

Os filtros são usados ​​para restringir os dados e eu usei o filtro de limite ainda mais para restringir os níveis de dados no fluxo. Mencionei os níveis que podem ser restringidos por lá. Para sua referência adicional, consulte a ordem dos níveis de log4j2 - Log4J: ALL> TRACE> DEBUG> INFO> WARN> ERRO> FATAL> OFF

saravanan
fonte
FilterRegistrationBeancomo mencionado na pergunta javax.servlet.Filter, esta resposta fala sobre #org.apache.logging.log4j.core.Filter
Steve Buzonas