Backend Development 11 min read

Secure Spring Boot 3 APIs: 5 Methods with Filters, Interceptors, AOP, OAuth2

This article presents five practical approaches to protect Spring Boot 3 API endpoints—including Filter, Interceptor, AOP combined with Filter, Spring Security, and OAuth2 integration—providing code examples, configuration steps, and screenshots to demonstrate authentication, authorization, and token handling for secure access control.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Secure Spring Boot 3 APIs: 5 Methods with Filters, Interceptors, AOP, OAuth2

API interfaces are the entry and exit points of core system data, so it is essential to prevent unauthorized access, data leakage, and malicious attacks. Common risks include exposing sensitive user information, allowing unauthorized operations, and resisting brute‑force or injection attacks.

Prevent visitors from viewing sensitive data such as user information.

Block unauthorized operations like a regular user deleting admin data.

Defend against malicious request flooding or injection attacks.

A proper permission control ensures data security, system stability, and compliance.

The article introduces five simple and effective protection schemes for API security.

Implementation via Filter

Implementation via Interceptor

Combination of AOP + Filter

Implementation using Spring Security

Integration with OAuth2

1. Filter Implementation

Filters are components defined by the Java Servlet specification that can intercept requests before they reach a servlet and responses before they are sent to the client. By implementing authentication logic in a filter, access to API endpoints can be effectively controlled.

<code>@WebFilter("/api/*")
public class JwtAuthFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        try {
            // Extract token from request header
            String token = JwtUtil.extractToken(request);
            // Validate token and store parsed data in thread context
            if (token != null && JwtUtil.validateToken(token)) {
                Map<String, Object> data = JwtUtil.parseToken(token);
                SecurityContext.set(data);
                filterChain.doFilter(request, resp);
            } else {
                // Authentication failed, return error response
                response.setContentType("application/json;charset=utf-8");
                response.getWriter().println(new ObjectMapper()
                        .writeValueAsString(Map.of("code", -1, "msg", "无效token")));
                return;
            }
        } finally {
            SecurityContext.clear();
        }
    }
}
</code>

This filter intercepts requests that start with /api .

Running result:

Providing a correct token and accessing again:

2. Interceptor Implementation

HandlerInterceptor is a Spring MVC interface that allows interception before and after request handling. Implementing its preHandle method enables permission verification before the request reaches the controller.

<code>@Component
public class AuthInterceptor implements HandlerInterceptor {
    private final ObjectMapper objectMapper;
    public AuthInterceptor(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = JwtUtil.extractToken(request);
        if (token != null && JwtUtil.validateToken(token)) {
            Map<String, Object> data = JwtUtil.parseToken(token);
            SecurityContext.set(data);
            return true;
        } else {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().println(objectMapper
                    .writeValueAsString(Map.of("code", -1, "msg", "无效token")));
            return false;
        }
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        SecurityContext.clear();
    }
}
</code>

Register the interceptor:

<code>@Component
public class WebConfig implements WebMvcConfigurer {
    private final AuthInterceptor authInterceptor;
    public WebConfig(AuthInterceptor authInterceptor) {
        this.authInterceptor = authInterceptor;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(this.authInterceptor).addPathPatterns("/api/**");
    }
}
</code>

3. AOP + Filter Implementation

AOP defines permission‑checking logic as an aspect, while a Filter intercepts requests and parses the token. This combination allows permission control at different stages of request processing, offering flexibility and efficiency.

Filter implementation:

<code>@WebFilter("/*")
public class TokenFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        try {
            String token = JwtUtil.extractToken(request);
            if (token != null && JwtUtil.validateToken(token)) {
                Map<String, Object> data = JwtUtil.parseToken(token);
                SecurityContext.set(data);
            }
            filterChain.doFilter(request, resp);
        } finally {
            SecurityContext.clear();
        }
    }
}
</code>

AOP aspect definition:

<code>@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionCheck {
    String[] value() default {};
}

@Aspect
@Component
public class PermissionAspect {
    @SuppressWarnings("unchecked")
    @Around("@annotation(permissionCheck)")
    public Object checkPermission(ProceedingJoinPoint joinPoint, PermissionCheck permissionCheck) throws Throwable {
        try {
            Map<String, Object> data = SecurityContext.get();
            if (data == null) {
                throw new PermissionException("无权限访问", 403);
            }
            String[] requiredRoles = permissionCheck.value();
            List<String> assignedRoles = (List<String>) data.get("roles");
            if (Collections.disjoint(List.of(requiredRoles), assignedRoles)) {
                throw new PermissionException("无权限访问", 403);
            }
            return joinPoint.proceed();
        } catch (Exception e) {
            e.printStackTrace();
            throw new PermissionException("Token无效或过期", 401);
        }
    }
}
</code>

Modify the controller to use the custom annotation:

<code>@GetMapping("/api/query")
@PermissionCheck({"api:query"})
public ResponseEntity<?> query() {
    return ResponseEntity.ok("query...");
}
</code>

4. Spring Security Implementation

Spring Security is the security framework of the Spring ecosystem, offering authentication, authorization, password encryption, and more. By configuring security rules and filter chains, fine‑grained permission control can be achieved easily.

Dependency:

<code><dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
</code>

Security configuration:

<code>@Configuration
public class SecurityConfig {
    @Bean
    SecurityFilterChain apiSecurity(HttpSecurity http) throws Throwable {
        http.csrf(csrf -> csrf.disable());
        http.securityMatcher("/api/**", "/login");
        http.formLogin(Customizer.withDefaults());
        http.authorizeHttpRequests(registry -> {
            registry.anyRequest().authenticated();
        });
        return http.build();
    }

    @Bean
    UserDetailsService userDetailsService() {
        UserDetails user = User.withUsername("pack")
                .password("{noop}123123")
                .roles("ADMIN")
                .build();
        return new InMemoryUserDetailsManager(user);
    }
}
</code>

When accessing /api/query , unauthenticated users are redirected to the login page (screenshots below).

5. OAuth2 Integration

For detailed guidance on integrating OAuth2 with Spring Boot for single sign‑on and resource protection, refer to the linked articles:

SpringBoot整合OAuth2实现单点登录

SpringBoot 整合 OAuth2 实现资源保护

These resources provide deeper insight into OAuth2 configuration and usage.

Overall, the five methods—Filter, Interceptor, AOP+Filter, Spring Security, and OAuth2—cover a range of scenarios from simple token checks to comprehensive security frameworks, enabling developers to protect Spring Boot 3 APIs effectively.

JavaSpring BootAuthenticationAPI securityAuthorization
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.