Filter in Spring Boot sind eine Möglichkeit, Anfragen und Antworten zu bearbeiten, bevor sie von einem Controller verarbeitet oder an den Client gesendet werden. Filter bieten eine flexible Möglichkeit, Aspekte wie Authentifizierung, Autorisierung, Logging, Caching, CORS (Cross-Origin Resource Sharing) und vieles mehr in den Request-Response-Zyklus einzubinden.
In diesem Kapitel werden wir erklären, wie Filter in Spring Boot REST Services funktionieren, wie sie erstellt und konfiguriert werden, und wie sie genutzt werden können, um typische Anforderungen wie Authentifizierung und Logging zu implementieren.
Ein Filter ist eine Komponente, die Anfragen und
Antworten auf dem Weg zum und vom Controller abfängt und manipulieren
kann. In Spring Boot wird dies durch das Implementieren der
javax.servlet.Filter-Schnittstelle
ermöglicht. Filter haben keinen direkten Zugriff auf den Controller oder
das Geschäftslogik-Schicht, sondern wirken auf die Anfragen, bevor sie
den Controller erreichen, oder auf die Antworten, bevor sie den Client
erreichen.
Ein Filter wird in Spring Boot durch das Implementieren der
Schnittstelle javax.servlet.Filter und die Implementierung
der Methode doFilter erstellt. Diese Methode wird für jede
Anfrage aufgerufen, die den Filter durchläuft.
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.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/products/*")
public class LoggingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Filter initialisieren
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("Anfrage wurde empfangen für: " + request.getRemoteAddr());
chain.doFilter(request, response); // Anfrage weiterleiten
System.out.println("Antwort wurde gesendet.");
}
@Override
public void destroy() {
// Filter aufräumen
}
}In diesem Beispiel protokolliert der LoggingFilter alle
eingehenden Anfragen und die dazugehörigen Antworten, die den
/products-Endpunkt betreffen. Der Filter greift auf die
Remote-Adresse des Clients zu, protokolliert sie und leitet dann die
Anfrage zur Weiterverarbeitung an die Kette der Filter und Controller
weiter.
In Spring Boot können Sie Filter auf zwei Arten registrieren: 1.
Durch das Verwenden der Annotation
@WebFilter wie oben gezeigt. 2. Durch
explizite Registrierung in einer
FilterRegistrationBean, die Ihnen mehr Kontrolle über
die Filterkonfiguration gibt.
FilterRegistrationBeanimport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<LoggingFilter> loggingFilter() {
FilterRegistrationBean<LoggingFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new LoggingFilter());
registrationBean.addUrlPatterns("/products/*");
return registrationBean;
}
}In diesem Beispiel wird der LoggingFilter über die
FilterRegistrationBean konfiguriert. Sie können den Filter
auf bestimmte URL-Muster anwenden und weitere Filtereinstellungen
vornehmen.
Eine häufige Verwendung von Filtern ist die Implementierung von Authentifizierung und Autorisierung. In diesem Fall prüft der Filter, ob ein Benutzer ein gültiges Token oder eine gültige Anmeldeinformation besitzt, bevor er den Zugriff auf die API-Endpunkte zulässt.
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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class JwtAuthenticationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String authHeader = httpRequest.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
return;
}
String token = authHeader.substring(7); // Extrahiert den JWT
// Validierung des JWT (Logik zur Validierung implementieren)
// Falls gültig, weiter zur nächsten Komponente in der Filterkette
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}In diesem Beispiel prüft der JwtAuthenticationFilter, ob
die Anfrage ein JWT im Authorization-Header enthält. Wenn
der JWT-Token nicht vorhanden oder ungültig ist, wird eine 401
Unauthorized-Antwort zurückgegeben.
In Spring Boot können Sie die Reihenfolge festlegen, in der Filter angewendet werden. Dies ist besonders wichtig, wenn Sie mehrere Filter haben, die in einer bestimmten Reihenfolge ausgeführt werden sollen.
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<LoggingFilter> loggingFilter() {
FilterRegistrationBean<LoggingFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new LoggingFilter());
registrationBean.addUrlPatterns("/products/*");
registrationBean.setOrder(1); // Reihenfolge festlegen (niedrigere Werte werden zuerst ausgeführt)
return registrationBean;
}
@Bean
public FilterRegistrationBean<JwtAuthenticationFilter> jwtFilter() {
FilterRegistrationBean<JwtAuthenticationFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new JwtAuthenticationFilter());
registrationBean.addUrlPatterns("/products/*");
registrationBean.setOrder(2); // Wird nach dem LoggingFilter ausgeführt
return registrationBean;
}
}In diesem Beispiel wird der LoggingFilter zuerst
ausgeführt, gefolgt vom JwtAuthenticationFilter, da der
LoggingFilter die niedrigere Priorität hat (Order 1).
CORS (Cross-Origin Resource Sharing) ist ein Mechanismus, der den Zugriff von verschiedenen Domains auf Ihre API steuert. Filter sind eine gute Möglichkeit, CORS in Spring Boot zu konfigurieren.
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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
httpResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
httpResponse.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) request).getMethod())) {
httpResponse.setStatus(HttpServletResponse.SC_OK);
return;
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}In diesem Beispiel setzt der CorsFilter die
entsprechenden CORS-Header, um den Zugriff von externen Domains zu
ermöglichen. Der Filter fängt auch OPTIONS-Anfragen ab, die
bei CORS-Vorabprüfungen verwendet werden.
Filter in Spring Boot bieten eine leistungsstarke Möglichkeit, Anfragen und Antworten auf niedriger Ebene zu bearbeiten, bevor sie den Controller erreichen. Sie eignen sich hervorragend für Aufgaben wie Authentifizierung, Logging, CORS und vieles mehr. Durch die einfache Implementierung und Konfiguration können Sie Filter flexibel an Ihre Anforderungen anpassen, um eine sichere und skalierbare RESTful Webservice-Architektur zu schaffen.