Four Ways to Implement a Generic AppKey Whitelist in Spring Boot
This article explains four approaches to adding a generic appkey whitelist check in a Spring Boot web framework—traditional AOP, HandlerInterceptor, custom HandlerMethodArgumentResolver, and Servlet Filter—providing implementation steps, code examples, and a discussion of their execution order and extensibility.
The article introduces four ways to implement a generic authentication (appkey) whitelist in a Spring Boot web framework, including traditional AOP, Interceptor, ArgumentResolver, and Filter, and provides corresponding example code along with a brief summary of their execution order.
Preface
Recently overwhelmed by endless business requirements, the author finally received a task that pushed them out of their comfort zone: adding a generic appkey whitelist validation feature to the internal web framework, aiming for better extensibility.
The framework, built on Spring Boot, sits between business code and the Spring framework, providing common utilities such as logging, feature toggles, and generic parameter parsing. The author decided to document the solution as a technical overview.
Traditional AOP
For this requirement, the first thought is to use Spring‑Boot's AOP support: declare a pointcut before controller methods and handle the whitelist check there.
Implementation
Steps:
Declare an aspect class with @Aspect , e.g., WhitelistAspect .
Add a pointcut method whitelistPointcut() that matches only methods annotated with a custom @Whitelist annotation.
Use @Before to define a advice method checkWhitelist() that runs before the controller method and performs the whitelist validation.
Aspect class pseudo‑code:
@Aspect
public class WhitelistAspect {
@Before(value = "whitelistPointcut() && @annotation(whitelist)")
public void checkAppkeyWhitelist(JoinPoint joinPoint, Whitelist whitelist) {
checkWhitelist();
// can use joinPoint.getArgs() to get controller method arguments
// can use whitelist variable to get annotation parameters
}
@Pointcut("@annotation(com.zhenbianshu.Whitelist)")
public void whitelistPointCut() {}
}Apply the @Whitelist annotation on controller methods to enable the check.
Extension
The example uses an annotation to declare the pointcut, and the annotation can be extended with additional attributes (e.g., uid() ) to support other whitelist criteria. Spring AOP also supports other pointcut expressions ( execution , bean ) and advice types ( @Around , @After ).
Interceptor
Spring's HandlerInterceptor is another suitable way. An interceptor runs before a controller action and can decide whether to allow the request.
Implementation
Steps:
Define an interceptor class WhitelistInterceptor that implements HandlerInterceptor .
Implement the preHandle() method to retrieve the @Whitelist annotation and perform the check; return false to block the request.
Optionally implement postHandle() and afterCompletion() for post‑processing.
Register the interceptor in a custom WebMvcConfigurerAdapter implementation.
Interceptor class:
@Component
public class WhitelistInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Whitelist whitelist = ((HandlerMethod) handler).getMethodAnnotation(Whitelist.class);
// whitelist.values(); // use request to get parameters, whitelist to get annotation values
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}Extension
Enable the interceptor by adding it in a configuration class that extends WebMvcConfigurerAdapter :
@Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new WhitelistInterceptor()).addPathPatterns("/*").order(1);
}
}Note that the interceptor returns HTTP 200 with an empty body when it allows the request.
ArgumentResolver
Spring's HandlerMethodArgumentResolver allows custom method‑parameter binding before the controller is invoked.
Implementation
Create a custom parameter type AuthParam containing appkey fields.
Implement AuthParamResolver that implements HandlerMethodArgumentResolver .
In supportsParameter() , return true when the method parameter type is AuthParam .
In resolveArgument() , obtain the request and the @Whitelist annotation, perform the whitelist check, and return an AuthParam instance.
Add AuthParam as a method argument in controller actions to activate the resolver.
Resolver class:
@Component
public class AuthParamResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(AuthParam.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Whitelist whitelist = parameter.getMethodAnnotation(Whitelist.class);
// validate whitelist using webRequest and whitelist
return new AuthParam();
}
}Extension
Register the resolver in the same WebMvcConfigurerAdapter implementation:
@Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List
argumentResolvers) {
argumentResolvers.add(new AuthParamResolver());
}
}Filter
A javax.servlet.Filter is defined by the Servlet specification and runs before Spring's dispatch. It cannot directly access Spring beans, so it works with raw ServletRequest and ServletResponse .
Implementation
Filter class:
public class WhitelistFilter implements javax.servlet.Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// decide whether to block the request
chain.doFilter(request, response); // must invoke to continue processing
}
@Override
public void destroy() {}
}Extension
Register the filter via a FilterRegistrationBean :
@Configuration
public class FilterConfiguration {
@Bean
public FilterRegistrationBean someFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new WhitelistFilter());
registration.addUrlPatterns("/*");
registration.setName("whitelistFilter");
registration.setOrder(1); // execution order
return registration;
}
}Summary
All four implementations are valid in different scenarios. Their invocation order is: Filter (Servlet level) → Interceptor → ArgumentResolver → AOP pointcut. Logging from a combined project confirms this sequence.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
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.