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.
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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.