Kotlin, Spring Boot : HandlerInterceptor vs Filter
HandlerInterceptor vs Filter in Spring Boot: A Practical Guide with JNDI Injection Prevention

Senior Android Engineer from Bangladesh. Love to contribute in Open-Source. Indie Music Producer.
In Spring Boot, both Filters and HandlerInterceptors help us intercept HTTP requests and responses, but they work at different levels in the app. Picking the right one depends on what you need—whether it's low-level request handling with a Filter or more Spring-aware processing with a HandlerInterceptor.
In this article, we'll explore:
Key Differences between
HandlerInterceptorandFilterWhen to Use Each
Code Examples (Including JNDI Injection Prevention at the Filter Layer)
Best Practices
HandlerInterceptor vs Filter: Core Differences
| Feature | HandlerInterceptor | Filter |
| Layer | Spring MVC (after DispatcherServlet) | Servlet (before DispatcherServlet) |
| Spring Context | Full DI support | ❌ No DI (unless manually bridged) |
| Access to | Controller metadata (e.g., @RequestMapping) | Raw ServletRequest/ServletResponse |
| Execution Order | After routing, before controller logic | Before Spring processes the request |
| Modify Response | Limited (cannot modify body easily) | Full control (via ServletResponse) |
| Use Cases | - Auth checks based on annotations | - Logging |
| - Request/response logging | - Request/response modification | |
| - Adding global model attributes | - Security (CORS, JNDI protection) |
When to Use Which?
Use
HandlerInterceptorWhen You Need:
Spring Dependency Injection (e.g.,
@Autowiredservices)Access to Controller Metadata (e.g., method annotations)
Pre/Post-Processing Around Controllers (e.g., logging execution time)
Use
FilterWhen You Need:
Low-Level Request/Response Manipulation (e.g., modifying headers)
Block Requests Before Spring Processes Them (e.g., security checks)
Servlet-Specific Features (e.g.,
HttpServletRequestwrappers)
Code Examples
Example 1: HandlerInterceptor (Spring-Aware)
@Component
class AuthInterceptor(
private val authService: AuthService // DI works
) : HandlerInterceptor {
override fun preHandle(
request: HttpServletRequest,
response: HttpServletResponse,
handler: Any
): Boolean {
if (!authService.isValidToken(request.getHeader("X-Auth-Token"))) {
response.status = HttpStatus.UNAUTHORIZED.value()
return false
}
return true
}
}
// Registration
@Configuration
class WebConfig : WebMvcConfigurer {
override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(AuthInterceptor())
}
}
Example 2: Filter (Servlet-Level)
Preventing JNDI Injection (Security Filter)
@Component
@Order(1) // High priority for security
class JndiInjectionFilter : Filter {
override fun doFilter(
request: ServletRequest,
response: ServletResponse,
chain: FilterChain
) {
val httpRequest = request as HttpServletRequest
// Block JNDI lookup attempts (e.g., Log4Shell)
if (httpRequest.queryString?.lowercase()?.contains("jndi:") == true) {
(response as HttpServletResponse).sendError(
HttpStatus.FORBIDDEN.value(),
"JNDI lookup blocked"
)
return
}
chain.doFilter(request, response)
}
}
Why This Works:
Filters run before Spring processes the request.
Blocks malicious
jndi:patterns (e.g., Log4Shell exploits).Does not rely on Spring (works at the servlet level).
Best Practices
Use
FiltersFor:
Security (e.g., JNDI, XSS, SQLi filters)
Infrastructure (e.g., logging, compression, CORS)
Request Wrapping (e.g., caching, modifying headers)
Use
HandlerInterceptorsFor:
Business Logic (e.g., role-based auth checks)
Controller-Specific Logic (e.g.,
@PreAuthorize-like checks)Post-Processing (e.g., adding response headers after execution)
Avoid:
Using Filters for Spring-specific tasks.
Using Interceptors for raw request/response modification.
Conclusion
| Aspect | Filter | HandlerInterceptor |
| Best For | Security, logging, raw manipulation | Business logic, Spring integration |
| Execution Point | Before Spring | After routing, before controller |
| Spring DI Support | No | Yes |
| Use Case Example | JNDI injection blocking | Role-based auth checks |
Final Recommendation
For security (e.g., JNDI, CORS) → Use
Filter.For Spring-aware logic (e.g., auth, logging) → Use
HandlerInterceptor.
That’s it for today. Happy coding…



