After Request Filtering Why It Is Going to Filter Again
Intro
Filter provides a user-friendly mechanism for inspecting and filtering HTTP requests entering your application. For instance, you want to inject a custom header to a request/response based on some conditions, or y'all desire to run some checks before accessing the controller and serve the request.
Bad
Sometimes nosotros meet people implement those kinds of checks and assertions in the controller. aye, information technology works but it's non the all-time place to put information technology there.
Skillful
Use Filters which it runs before accessing the controllers and serve your requests.
Filters period
Easily On
How to write?
In lodge to create a request filter. you just need to create a class that implements the Filter interface.
package com.ahmedash95.instance.filters ; import javax.servlet.* ; @Component public class RoomsCreateFilter implements Filter { @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { // your code goes here. // then you lot demand to laissez passer it in the concatenation. chain . doFilter ( request , response ); } }
If you lot are non familiar with the code in a higher place. hither are some clarifications:
-
@Componentis an note that allows us to register the class equally a edible bean in the ApplicationContext -
implements Filterinterface tells Spring how this class should be used when register via@Component -
import javax.servlet.*;imports Filter, ServletRequest, ServletResponse, FilterChain, and ServletException. -
chain.doFilter(request, response);at the end is a must. every bit it tells bound how to continue handling the asking. without it the response will be empty equally the chain got broken.
Return response on errors
If you validate something and want to end processing the request and merely render the response. you can simply modify the Response object and render it from your Filter class.
@Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { boolean valid = false ; // check for something if (! valid ) { (( HttpServletResponse ) response ). setStatus ( 422 ); response . getOutputStream (). write ( "Validation error" . getBytes ()); return ; } concatenation . doFilter ( request , response ); }
Examples
Let's write some existent-world examples and some unlike scenarios to make certain you get the full picture show.
i.Ensure API key is provided and valid
Let's say you are working on API that provides something. and you want to ensure that all requests to your application will have the API central and the key is valid. of course, you don't want to do the key validation to be in every controller and method.
Let'southward start by creating our filter first
package com.example.demo ; import coffee.io.IOException ; import javax.servlet.* ; import javax.servlet.http.HttpServletRequest ; import javax.servlet.http.HttpServletResponse ; import org.springframework.stereotype.Component ; @Component public class APIKeyValidatorFilter implements Filter { @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain concatenation ) throws IOException , ServletException { HttpServletRequest req = ( HttpServletRequest ) request ; String key = req . getHeader ( "X-API-Primal" ); if ( key == cypher ) { (( HttpServletResponse ) response ). setStatus ( 401 ); response . getOutputStream (). write ( "API Key is missing!" . getBytes ()); return ; } if (! KeyValidator . valid ( fundamental )) { (( HttpServletResponse ) response ). setStatus ( 403 ); response . getOutputStream (). write ( "API Key is invalid" . getBytes ()); return ; } chain . doFilter ( asking , response ); } }
As you lot run into. we basically do some checks. if the cardinal is not provided we show the key missing error message. if is provided but not valid nosotros evidence The cardinal is an invalid message.
2.Ratelimit some endpoints
Let's say you want to protect the Post /annotate endpoint. so your users must not be able to submit more than than 2 comments in one minute. Again it can be washed in the controller simply It's not the all-time place to practice it.
Let's create the Filter form
bundle com.example.demo ; import javax.servlet.Filter ; import java.io.IOException ; import javax.servlet.* ; import javax.servlet.http.HttpServletResponse ; public course PostCommentRateLimit implements Filter { RateLimiter rateLimiter ; public PostCommentRateLimit ( RateLimiter rateLimiter ) { this . rateLimiter = rateLimiter ; } @Override public void doFilter ( ServletRequest asking , ServletResponse response , FilterChain chain ) throws IOException , ServletException { int userId = 1 ; // Become User boolean valid = rateLimiter . validate ( Cord . format ( "ratelimit.user.comments:%d" , userId ), two ); if (! valid ) { (( HttpServletResponse ) response ). setStatus ( 429 ); response . getOutputStream (). write ( "Also Many Requests" . getBytes ()); return ; } chain . doFilter ( request , response ); } }
Few things to explain here:
- We did non employ
@Componenthither. because we want to use the filter onMail service /commentendpoint only. so nosotros will annals information technology ourself next. - We have
RateLimiterin constructor. and you lot don't need to worry about it. use whatever library fits your needs.
Equally mentioned nosotros did not use @Component considering information technology would apply the filter for all requests. instead nosotros will create some other class to annals our filters the way we want.
package com.example.demo ; import org.springframework.beans.factory.annotation.Autowired ; import org.springframework.boot.spider web.servlet.FilterRegistrationBean ; import org.springframework.context.note.Bean ; import org.springframework.context.annotation.Configuration ; @Configuration public class RequestsFilterRegister { @Autowired RateLimiter rateLimiter ; @Bean public FilterRegistrationBean < PostCommentRateLimit > registerPostCommentsRateLimiter (){ FilterRegistrationBean < PostCommentRateLimit > registrationBean = new FilterRegistrationBean <>(); registrationBean . setFilter ( new PostCommentRateLimit ( rateLimiter )); registrationBean . addUrlPatterns ( "/comment" ); return registrationBean ; } }
- We created
RequestsFilterRegisteras@Configurationclass - The but method there
registerPostCommentsRateLimiterto annals the filter as nosotros want. - we used
addUrlPatternsto apply the filter only on/commentendpoint.
Now we have i minor problem. the filter is applied to any method on /annotate either GET or Postal service. and to fix that we just demand to modify the PostCommentRateLimit@doFilter to skip if the method is not post
HttpServletRequest req = ( HttpServletRequest ) request ; if (! req . getMethod (). equals ( "Mail service" )) { concatenation . doFilter ( request , response ); render ; }
Now the full class is
packet com.instance.demo ; import javax.servlet.Filter ; import coffee.io.IOException ; import javax.servlet.* ; import javax.servlet.http.HttpServletRequest ; import javax.servlet.http.HttpServletResponse ; public class PostCommentRateLimit implements Filter { RateLimiter rateLimiter ; public PostCommentRateLimit ( RateLimiter rateLimiter ) { this . rateLimiter = rateLimiter ; } @Override public void doFilter ( ServletRequest asking , ServletResponse response , FilterChain chain ) throws IOException , ServletException { HttpServletRequest req = ( HttpServletRequest ) request ; if (! req . getMethod (). equals ( "POST" )) { concatenation . doFilter ( asking , response ); return ; } int userId = one ; // Get User boolean valid = rateLimiter . validate ( String . format ( "ratelimit.user.comments:%d" , userId ), 2 ); if (! valid ) { (( HttpServletResponse ) response ). setStatus ( 429 ); response . getOutputStream (). write ( "Too Many Requests" . getBytes ()); render ; } chain . doFilter ( request , response ); } }
Conclution
Now you know What is Request Filters, how to write them, and y'all applied some real-world examples. also you saw how to customize the routes and methods to utilize filters on.
The full source code https://github.com/ahmedash95/java-spring-request-filters
For more, you can check baeldung.com/spring-boot-add-filter
Note
I'thou yet learning Java and jump. and then if yous encounter any mistakes or a better mode in writing Filters Your comments and suggestions volition be greatly appreciated.
Source: https://dev.to/ahmedash95/java-springboot-request-filters-15ha
0 Response to "After Request Filtering Why It Is Going to Filter Again"
Post a Comment