จะเพิ่มคลาสตัวกรองใน Spring Boot ได้อย่างไร


229

ฉันสงสัยว่าถ้ามีคำอธิบายประกอบสำหรับFilterคลาส (สำหรับเว็บแอปพลิเคชัน) ใน Spring Boot หรือไม่ อาจจะ@Filter?

ฉันต้องการเพิ่มตัวกรองที่กำหนดเองในโครงการของฉัน

คู่มืออ้างอิงเกี่ยวกับSpring Bootกล่าวถึง FilterRegistrationBeanแต่ฉันไม่แน่ใจว่าจะใช้งานอย่างไร


โปรดทราบว่าตัวกรองที่ถูกเพิ่มด้วย @WebFilter ไม่ทำงานเหมือนตัวกรองจริงในข้อมูลจำเพาะของ Servlet มันจะเป็นสปริงถั่วที่ถูกเรียกใช้หลังจากสปริงอื่น ๆ จำนวนมากและไม่ชอบตัวกรองจริง ๆ ก่อนโค้ด servlet ใด ๆ
lrxw

คุณสามารถบอกฉันว่าคุณต้องการที่แน่นอน หากคุณต้องการคลาสตัวกรองสำหรับ ComponentScan แสดงว่ามีคำอธิบายประกอบสำหรับ "@ ComponentScan.Filter"
Keaz

คำตอบ:


159

FilterRegistrationBeanหากคุณต้องการที่จะติดตั้งตัวกรองบุคคลที่สามคุณสามารถใช้ ตัวอย่างเช่นเทียบเท่ากับ 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>

สิ่งเหล่านี้จะเป็นสองถั่วใน@Configurationไฟล์ของคุณ

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

ข้างต้นได้รับการทดสอบกับ spring-boot 1.2.3


1
ถ้าฉันต้องการเพิ่มตัวกรองมากกว่าหนึ่งตัวล่ะ @Opal
verystrongjoe

8
เพียงแค่เพิ่ม @Bean พับลิกสาธารณะ FilterRegistrationBeanFilterRegistration ()
ฮาอิมรามาน

เราจะทราบลำดับที่ใช้ตัวกรองได้อย่างไร
BeepDog

7
FilterRegistrationBean.setOrder
ฮาอิมรามาน

คุณไม่จำเป็นต้องใช้ filter bean เมื่อคุณเรียกใช้เมธอดsomeFilter()โดยตรง
wst

117

นี่คือตัวอย่างของวิธีหนึ่งในการรวมตัวกรองที่กำหนดเองในแอปพลิเคชัน Spring Boot MVC ตรวจสอบให้แน่ใจว่าได้รวมแพ็คเกจในการสแกนส่วนประกอบ:

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 {}

}

4
ควรลงทะเบียนตัวกรองที่ไหนสักแห่งหรือไม่
gstackoverflow

1
เมื่อฉันพยายามวิธีการที่กรองถูกสร้างขึ้นเป็นถั่วและแม้กระทั่งถูกฉีดเข้าชั้นเรียนอื่น ๆแต่ init () วิธีการไม่ได้วิ่ง อาจเริ่มต้น () ทำงานเฉพาะในการลงทะเบียน 'ปกติ' ไม่ได้โดยภาชนะฤดูใบไม้ผลิ ฉันคิดว่าอาจใช้ PostConstruct แทน init () แต่ฉันไม่ได้ลองเพราะฉันปฏิเสธการประกาศตัวกรองเป็น Spring bean
Baurzhan

การสั่งซื้อตัวกรองโดยใช้วิธีการนี้เป็นอย่างไร
Pavel Vlasov

เราจะรับ RS body จาก ServletResponse ได้อย่างไร?
user2602807

1
สิ่งสำคัญที่ควรทราบคือชื่อของถั่ว (ตามชื่อคลาสของคุณ) ไม่ควรเหมือนกับ Spring bean ตัวอย่างเช่นคุณอาจถูกล่อลวงให้สร้างMetricsFilterแต่ถั่วนี้จะถูกบดบังด้วย Spring actuator bean ที่ชื่อเดียวกัน เรียนรู้วิธีนี้ยาก ...
kinbiko

78

ไม่มีหมายเหตุประกอบแบบพิเศษที่แสดงถึงตัวกรองเซิร์ฟเล็ต คุณเพิ่งประกาศ@BeanประเภทFilter(หรือFilterRegistrationBean) ตัวอย่าง (เพิ่มส่วนหัวที่กำหนดเองและการตอบทั้งหมด) อยู่ในตัวเอง Boot ของEndpointWebMvcAutoConfiguration ;

หากคุณประกาศเท่านั้นFilterจะมีผลกับคำขอทั้งหมด หากคุณเพิ่มFilterRegistrationBeanคุณยังสามารถระบุแต่ละเซิร์ฟเล็ตและรูปแบบ URL ที่จะใช้เพิ่มเติม

บันทึก:

ตั้งแต่ Spring Boot 1.4 FilterRegistrationBeanไม่เลิกใช้และย้ายแพ็คเกจจากorg.springframework.boot.context.embedded.FilterRegistrationBeanไปยังorg.springframework.boot.web.servlet.FilterRegistrationBean


คุณช่วยบอกวิธีรวมรายการที่สอดคล้องกันใน build.gradle ได้อย่างไร ฉันได้เพิ่มสิ่งต่อไปนี้ แต่ไม่ได้รับการคอมไพล์: providedCompile ('javax.servlet: servlet-api: 2.5') runtime ('javax.servlet: jstl: 1.1.2')
janetsmith

2
Spring Boot จะไม่ทำงานกับ Servlet 2.5 และยังไม่ได้รับการสนับสนุนอย่างมากสำหรับ JSP ฉันไม่ใช่นักเรียนระดับประถมดังนั้นฉันไม่รู้ว่าคุณกำลังพยายามทำอะไร เกิดอะไรขึ้นกับ "คอมไพล์"? มันใช้งานได้ไหมถ้าคุณพึ่งพึ่ง "spring-boot-starter-web"? (ผมไม่คิดว่าคำถามเหล่านี้จะเกี่ยวข้องกับคำถามเดิมแม้ว่าดังนั้นบางทีคุณควรโพสต์อีกครั้งกับคำถามใหม่?)
เดฟ Syer

ฉันเพิ่มตัวกรองโดยใช้ตัวกรองอินเตอร์เฟสอย่างไรก็ตาม Eclipse ไม่พบอินเทอร์เฟซ ดังนั้นฉันจึงพยายามหาวิธีเพิ่มลงใน classpath สำหรับการรวบรวม
Janetsmith

1
ใช่แน่นอนคุณต้องมีFilterใน classpath ของคุณ โดยปกติฉันจะใช้spring-boot-starter-webเพื่อดึงในการ depdendencies ที่เกี่ยวข้องทั้งหมด (เช่นที่นี่ )
Dave Syer

เช่นเดียวกับรายละเอียดการตอบกลับอื่น ๆ คุณสามารถใส่คำอธิบายประกอบคลาสตัวกรองของคุณด้วย @Component และมันจะถูกลงทะเบียนโดยอัตโนมัติ (สำหรับ URL ทั้งหมด)
Jakub Holý

72

มีสามวิธีในการเพิ่มตัวกรองของคุณ

  1. คำอธิบายประกอบตัวกรองของคุณด้วยหนึ่งในแบบแผนสปริงเช่น @Component
  2. ลงทะเบียน@BeanกับFilterประเภทในฤดูใบไม้ผลิ@Configuration
  3. ลงทะเบียน@BeanกับFilterRegistrationBeanประเภทในฤดูใบไม้ผลิ@Configuration

# 1 หรือ # 2 จะทำอย่างไรถ้าคุณต้องการให้ตัวกรองของคุณนำไปใช้กับคำขอทั้งหมดโดยไม่ต้องปรับแต่งใช้อย่างอื่น # 3 คุณไม่จำเป็นต้องระบุการสแกนส่วนประกอบเพื่อให้ # 1 ทำงานได้ตราบใดที่คุณวางคลาสตัวกรองของคุณในแพคเกจย่อยหรือSpringApplicationคลาสเดียวกัน สำหรับ # 3 ใช้พร้อมกับ # 2 เป็นสิ่งจำเป็นเฉพาะเมื่อคุณต้องการให้ Spring จัดการคลาสตัวกรองของคุณเช่นมีการพึ่งพาสายอัตโนมัติ มันใช้งานได้ดีสำหรับฉันในการสร้างตัวกรองใหม่ซึ่งไม่ต้องการการพึ่งพา / การฉีดอัตโนมัติ

แม้ว่าการรวม # 2 และ # 3 ทำงานได้ดีฉันก็แปลกใจที่มันไม่ได้จบลงด้วยตัวกรองสองตัวที่ใช้สองครั้ง ฉันเดาว่าฤดูใบไม้ผลิรวมสองถั่วเป็นหนึ่งเมื่อเรียกวิธีเดียวกันเพื่อสร้างทั้งสองอย่าง ในกรณีที่คุณต้องการใช้ # 3 คนเดียวกับ authowiring AutowireCapableBeanFactoryคุณสามารถ ต่อไปนี้เป็นตัวอย่าง

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;
    }

คำตอบที่ยอดเยี่ยม ขอขอบคุณที่ให้รายละเอียดตัวเลือกทั้งหมดและยังครอบคลุมถึงวิธีการคำนวณอัตโนมัติFilterขณะใช้งานFilterRegistrationBean
sbk

คำตอบที่ดี นี่คือสิ่งที่ฉันเคยชิน !!
haykart

นี่คือคำอธิบายที่นี่: baeldung.com/spring-boot-add-filter
Jakub Holý

31

ปรับปรุง: 2017-12-16:

มี 2 ​​วิธีง่าย ๆ ในการทำ Spring Boot 1.5.8 การเปิดตัวไม่จำเป็นต้องใช้ XML

วิธีแรก: หากคุณไม่มีรูปแบบ URL ใด ๆ คุณสามารถใช้ @Component ดังนี้: (รหัสเต็มและรายละเอียดอยู่ที่นี่https://www.surasint.com/spring-boot-filter/ )

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

วิธีที่สอง: หากคุณต้องการใช้รูปแบบ URL คุณสามารถใช้ @WebFilter เช่นนี้: (รหัสเต็มและรายละเอียดอยู่ที่นี่https://www.surasint.com/spring-boot-filter-urlpattern/ )

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

แต่คุณต้องเพิ่มคำอธิบายประกอบ @ServletComponentScan ในคลาส @SpringBootApplication ของคุณ:

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

โปรดทราบว่า @Component เป็นคำอธิบายประกอบของ Spring แต่ @WebFilter ไม่ใช่ @WebFilter เป็นคำอธิบายประกอบ Servlet 3

ทั้งสองวิธีคุณเพียงแค่ต้องพึ่งพา Spring Boot พื้นฐานใน pom.xml (ไม่จำเป็นต้องใช้ 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>

คำเตือน:วิธีแรกถ้าตัวควบคุมใน Spring Boot กลับไปเป็นไฟล์ JSP คำขอจะผ่านตัวกรองสองครั้ง

ในขณะที่ในทางที่สองคำขอจะผ่านตัวกรองเพียงครั้งเดียว

ฉันชอบวิธีที่สองมากกว่าเพราะมันคล้ายกับพฤติกรรมเริ่มต้นในข้อกำหนดคุณสมบัติของ Servlet ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html )

คุณสามารถดูบันทึกการทดสอบเพิ่มเติมได้ที่นี่https://www.surasint.com/spring-boot-webfilter-instead-of-component/


ฉันเห็นว่าFilterอินเทอร์เฟซถูกเรียกหลายครั้งระหว่างเรียกใช้ applicationContext มีวิธีดำเนินการเพียงครั้งเดียวเท่านั้นหรือไม่?
Pra_A

@PAA คุณหมายถึงจากตัวอย่างของฉัน?
Surasin Tancharoen

20

นี่คือตัวอย่างของคลาสตัวกรองที่กำหนดเองของฉัน:

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

และฉันเพิ่มลงในการกำหนดค่าการบู๊ตสปริงโดยเพิ่มลงในคลาสการกำหนดค่าดังต่อไปนี้:

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;
    }
}

14

จาก Spring docs

คอนเทนเนอร์ servlet แบบฝัง - เพิ่ม Servlet, Filter หรือ Listener ให้กับแอปพลิเคชัน

ในการเพิ่ม Servlet, Filter หรือ Servlet * Listener จะมี คำนิยาม@Beanสำหรับมัน

เช่น:

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

เพิ่มการกำหนดค่านี้@Beanใน@Configurationชั้นเรียนของคุณและตัวกรองจะได้รับการลงทะเบียนเมื่อเริ่มต้น

นอกจากนี้คุณสามารถเพิ่ม Servlets, ฟิลเตอร์และ Listeners โดยใช้การสแกนคลาสพา ธ

@WebServlet, @WebFilter และ @WebListener คลาสที่ทำหมายเหตุประกอบไว้สามารถลงทะเบียนโดยอัตโนมัติด้วยคอนเทนเนอร์ servlet แบบฝังโดยใส่คำอธิบายประกอบคลาส @Configuration ด้วย @ServletComponentScan และระบุแพ็คเกจที่มีส่วนประกอบที่คุณต้องการลงทะเบียน โดยค่าเริ่มต้น @ServletComponentScan จะสแกนจากแพ็คเกจของคลาสที่มีคำอธิบายประกอบ


docs.spring.io/spring-boot/docs/current/reference/html/…ไม่ทำงานสำหรับฉัน แต่docs.spring.io/spring-boot/docs/1.5.8.RELEASE/reference/html/…ใช้งานไม่ได้ สำหรับฉัน.
user674669

7

หากคุณใช้ Spring Boot + Spring Security คุณสามารถทำได้ในการกำหนดค่าความปลอดภัย

ในตัวอย่างด้านล่างฉันกำลังเพิ่มตัวกรองแบบกำหนดเองก่อน UsernamePasswordAuthenticationFilter (ดูตัวกรอง Spring Security เริ่มต้นทั้งหมดและคำสั่งของพวกเขา )

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

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

และตัวกรองคลาส

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

5

การใช้คำอธิบายประกอบ @WebFilter สามารถทำได้ดังนี้:

@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

    }

}

3
เพิ่ม @ServletComponentScan
Justas

5

ขณะนี้มีประมาณสี่ตัวเลือกที่แตกต่างกันเพื่อลงทะเบียนตัวกรองใช้ Spring

ประการแรกเราสามารถสร้าง Spring bean Implement Filterหรือขยาย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);
    }
}

ประการที่สองเราสามารถสร้าง Spring bean ที่ขยาย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);
    }
}

หรือเราสามารถใช้คลาส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;
    }
}

และสุดท้ายเราสามารถใช้@WebFilterคำอธิบายประกอบกับ@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);
    }
}

ตัวกรองใดที่จะใช้และทำไม
Pra_A

3

มันเป็นคำแนะนำมากกว่าคำตอบ แต่ถ้าคุณใช้ Spring MVC ในเว็บแอปพลิเคชันของคุณคุณควรใช้ Spring HandlerInterceptor แทนตัวกรอง

มันสามารถทำงานเดียวกัน แต่ยัง - สามารถทำงานกับ ModelAndView - สามารถเรียกวิธีการก่อนและหลังการประมวลผลคำขอหรือหลังจากเสร็จสิ้นการร้องขอ
- สามารถทดสอบได้ง่าย

1 ติดตั้งอินเตอร์เฟส HandlerInterceptor และเพิ่มคำอธิบายประกอบ @Component ให้กับคลาสของคุณ

@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 กำหนดค่า 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");
    }

}

เรียบง่ายและสง่างาม! ขอบคุณ
MrMins

3

ตัวกรองนี้จะช่วยให้คุณอนุญาตการเข้าถึงข้ามต้นทาง

@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

    }

}

2

คุณสามารถใช้ @WebFilter javax.servlet.annotation.WebFilter ในคลาสที่ใช้ javax.servlet.Filter

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

จากนั้นใช้ @ServletComponentScan เพื่อลงทะเบียน


2

ฉันเห็นคำตอบมากมายที่นี่ แต่ฉันไม่ได้ลองเลย ฉันเพิ่งสร้างตัวกรองตามรหัสต่อไปนี้

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

    }
}

และปล่อยแอปพลิเคชั่น Spring Boot ที่เหลืออยู่ตามเดิม


2

คุณต้องมี 2 สิ่งสำคัญ: - เพิ่ม@ServletComponentScanไปยังคลาสหลักของคุณ - คุณสามารถเพิ่มแพ็คเกจชื่อตัวกรองในนั้นคุณสร้างFilterคลาสที่มีดังต่อไปนี้:

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

1

คุณยังสามารถสร้างตัวกรองโดยใช้ @WebFilter และใช้ตัวกรองซึ่งจะทำ

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

1

ตัวกรองเป็นชื่อที่แนะนำให้ใช้ในการกรองบนการร้องขอไปยังทรัพยากรหรือการตอบสนองจากทรัพยากรหรือทั้งสองอย่าง Spring Boot มีตัวเลือกน้อยเพื่อลงทะเบียนตัวกรองที่กำหนดเองในแอปพลิเคชัน Spring Boot ลองดูที่ตัวเลือกต่าง ๆ

1. กำหนดตัวกรองการบูตในฤดูใบไม้ผลิและคำสั่งการขอร้อง

ใช้อินเตอร์เฟสตัวกรองเพื่อสร้างตัวกรองใหม่ใน 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
 }
}

เรามาดูจุดสำคัญในโค้ดด้านบนกันอย่างรวดเร็ว

  • ตัวกรองที่ลงทะเบียนโดยคำอธิบายประกอบ@Component
  • หากต้องการเริ่มต้นตัวกรองในลำดับที่ถูกต้อง - เราต้องใช้คำอธิบายประกอบ@Order

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

ในรหัสข้างต้น CustomFirstFilter จะทำงานก่อน CustomSecondFilter

จำนวนที่ต่ำกว่าลำดับความสำคัญที่สูงกว่า

2. รูปแบบ URL

หากการแมปตามการประชุมไม่ยืดหยุ่นเพียงพอเราสามารถใช้FilterRegistrationBeanสำหรับการควบคุมแอปพลิเคชันทั้งหมด ที่นี่ไม่ได้ใช้@Componentคำอธิบายประกอบสำหรับการเรียนกรอง แต่ลงทะเบียนกรองโดยใช้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() {

 }
}

ลงทะเบียนตัวกรองที่กำหนดเองโดยใช้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;
 }
}

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... ");
        }

    }

คุณต้องใช้ตัวกรองและจำเป็นต้องใส่คำอธิบายประกอบด้วย @WebFilter (urlPatterns = "/ *")

และในแอปพลิเคชันหรือคลาสการกำหนดค่าคุณต้องเพิ่ม @ServletComponentScan โดยตัวกรองของคุณจะได้รับการลงทะเบียน


นี่@WebFilterเป็นเพียงตั้งแต่ Servlet 3.0 ดังนั้นจึงอาจไม่ทำงานอย่างถูกต้องสำหรับ 2.5
ha9u63ar

1

ขั้นตอนที่ 1: สร้างองค์ประกอบตัวกรองโดยใช้ตัวกรองส่วนต่อประสาน

@Component
public class PerformanceFilter implements Filter {

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

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

}

ขั้นตอนที่ 2: ตั้งค่าตัวกรองนี้เป็นรูปแบบ uri โดยใช้ FilterRegistrationBean

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

คุณสามารถอ้างอิงลิงค์นี้สำหรับแอปพลิเคชันที่สมบูรณ์


0

ก่อนอื่นให้เพิ่ม@ServletComponentScanคลาส SpringBootApplication ของคุณ

@ServletComponentScan
public class Application {

ขั้นที่สองสร้างไฟล์ตัวกรองส่วนขยายตัวกรองหรือคลาสตัวกรองบุคคลที่สามและเพิ่มลง@WebFilterในไฟล์นี้ดังนี้:

@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{

0

ฉันเห็นคำตอบของ @Vasily Komarov วิธีการที่คล้ายกัน แต่ใช้นามธรรมHandlerInterceptorAdapter คลาสแทนการใช้HandlerInterceptor HandlerInterceptor

นี่คือตัวอย่าง ...

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

}

0

ดังที่คุณทราบกันดีแล้ว Spring Boot เป็นวิธีที่ยอดเยี่ยมในการพัฒนา WebApp หรือ StandaloneApp ด้วยการกำหนดค่าขั้นต่ำและการตั้งค่าที่ให้ความเห็น

นี่คือวิธีที่ฉันประสบความสำเร็จในการพัฒนา Web Filter ในแอปพลิเคชัน Spring Boot

My SpringBootApp ข้อมูลจำเพาะ: -

เวอร์ชั่น Spring Boot: 2.0.4.RELEASE
เวอร์ชั่น Java: 8.0
Servlet Specification: Servlet 3.0 (จำเป็นและสำคัญ)

ฉันประกาศตัวกรองเว็บของฉันในลักษณะต่อไปนี้โดยปฏิบัติตามข้อกำหนดคุณสมบัติของ Servlet 3.0

ป้อนคำอธิบายรูปภาพที่นี่ นี่คือวิธีการโปรแกรมในการกำหนดตัวกรองแทนคำจำกัดความที่ใช้ web.xml

คำอธิบายประกอบ "@Webfilter" จะถูกประมวลผลโดยคอนเทนเนอร์ระหว่างการปรับใช้คลาสตัวกรองที่พบจะถูกสร้างขึ้นตามการกำหนดค่าและนำไปใช้กับรูปแบบ URL, javax.servlet.Servlets และ javax.servlet.DispatcherTypes

เพื่อหลีกเลี่ยง Web.xml อย่างสมบูรณ์และเพื่อให้บรรลุ WebApp "Deployable": -

ในการปรับใช้ Spring Boot Application เป็น "Traditional WAR" คลาสแอ็พพลิเคชันควรขยาย SpringBootServletInitializer

หมายเหตุ :: SpringBootServletInitializer เป็น "การใช้งานแบบโปรแกรม" ของ web.xml โดยอ้างอิงกับข้อกำหนดของ Servlet 3.0+ ซึ่งต้องการการใช้งานของ WebApplicationInitializer

ดังนั้น SpringBootApplication ไม่จำเป็นต้องใช้ "web.xml" เป็นคลาสแอปพลิเคชัน (หลังจากขยาย SpringBootServletInitializer) เพื่อสแกนหา
- @WebFilter,
- @WebListener และ
- @WebServlet

คำอธิบายประกอบ @ServletComponentScan

คำอธิบายประกอบนี้เปิดใช้งานการสแกนแพ็กเกจฐานสำหรับคอมโพเนนต์ของเว็บที่ใส่คำอธิบายประกอบด้วย @WebFilter, @WebListener และ @WebServlet

เนื่องจากความจริงที่ว่าคอนเทนเนอร์แบบฝังไม่สนับสนุน @WebServlet, @WebFilter และ @WebListener คำอธิบายประกอบ, Spring Boot ใช้การพึ่งพาอย่างมากกับคอนเทนเนอร์แบบฝังจึงแนะนำคำอธิบายประกอบใหม่นี้ @ServletComponentScan

การสแกนจะดำเนินการเมื่อใช้คอนเทนเนอร์ Servlet แบบฝังเท่านั้น

ต่อไปนี้เป็นคำนิยามคลาส Spring Application ของฉัน: -

ป้อนคำอธิบายรูปภาพที่นี่

เครื่องมือกำหนดค่าเริ่มต้น Servlet แบบกำหนดเอง: -

ที่นี่: ฉันได้กำหนดคลาสที่กำหนดเอง: "ServletInitializer" ซึ่งขยายคลาส: SpringBootServletInitializer

ตามที่อธิบายไว้ก่อนหน้านี้ SpringBootServletInitializer รับผิดชอบการสแกนหมายเหตุประกอบ: -
- @WebFilter
- @WebListener และ
- @WebServlet

ดังนั้น Spring Application Application Class จึงควร

  • ขยายคลาส: SpringBootServletInitializer หรือ
  • ขยายคลาสที่กำหนดเองซึ่งขยายคลาส: SpringBootServletInitializer

ป้อนคำอธิบายรูปภาพที่นี่


-6

ตัวกรองส่วนใหญ่จะใช้ในไฟล์ตัวบันทึกซึ่งแตกต่างกันไปตามตัวบันทึกที่คุณใช้ในโครงการ Lemme อธิบายสำหรับ 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>

ตัวกรองถูกใช้เพื่อ จำกัด ข้อมูลและฉันใช้ตัวกรองขีด จำกัด เพิ่มเติมเพื่อ จำกัด ระดับข้อมูลในโฟลว์ที่ฉันกล่าวถึงระดับที่สามารถ จำกัด ได้ที่นั่น สำหรับการอ้างอิงเพิ่มเติมของคุณดูลำดับของ log4j2 - ระดับ Log4J: ทั้งหมด> TRACE> DEBUG> INFO> WARN> ERROR> FATAL> OFF


FilterRegistrationBeanตามที่กล่าวไว้ในคำถามสำหรับjavax.servlet.Filterคำตอบนี้พูดถึงorg.apache.logging.log4j.core.Filter
สตีฟ Buzonas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.