# Kotlin, Spring Boot : HandlerInterceptor vs Filter

%[https://ylnk.cc/] 

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:

1. **Key Differences** between `HandlerInterceptor` and `Filter`
    
2. **When to Use Each**
    
3. **Code Examples** (Including **JNDI Injection Prevention** at the Filter Layer)
    
4. **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** `HandlerInterceptor` When You Need:

* **Spring Dependency Injection** (e.g., `@Autowired` services)
    
* **Access to Controller Metadata** (e.g., method annotations)
    
* **Pre/Post-Processing Around Controllers** (e.g., logging execution time)
    

> **Use** `Filter` When 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., `HttpServletRequest` wrappers)
    

## ***Code Examples***

> **Example 1: HandlerInterceptor (Spring-Aware)**

```kotlin
@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)

```kotlin
@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** `Filters` **For:**

* **Security** (e.g., JNDI, XSS, SQLi filters)
    
* **Infrastructure** (e.g., logging, compression, CORS)
    
* **Request Wrapping** (e.g., caching, modifying headers)
    

> Use `HandlerInterceptors` For:

* **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…
