thank you for your time. I use Spring boot 3.4.0 and I want to throw an exception in filter, but it doesn't work...
Everything is correct according to the breakpoints and logs, but my response body is empty.
The filter:
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
@Qualifier("handlerExceptionResolver")
private HandlerExceptionResolver resolver;
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader("Authorization");
try {
if (token.startsWith("Basic ")) {
String codeId = request.getParameter("codeId");
String text = request.getParameter("text");
CaptchaCode captchaCode = new CaptchaCode(codeId, text, null);
captchaCodeApplicationService.isCoptchaCodeValid(captchaCode);
}
...
} catch (ValidationException e) {
resolver.resolveException(request, response, null, e);
}
}
}
The advice:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ValidationException.class)
public ResponseEntity<?> handlerValidationException(ValidationException e, WebRequest request) {
ExceptionDetails details = new ExceptionDetails(
LocalDateTime.now(),
HttpStatus.BAD_REQUEST.name(),
request.getDescription(false),
e.getMessage()
);
return new ResponseEntity<>(details, HttpStatus.BAD_REQUEST);
}
}
The securityConfig:
@Configuration
@EnableWebSecurity
public class SecuirtyConfig {
@Autowired
UserApplicationService userApplicationService;
@Autowired
private JwtAuthenticationFilter jwtFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity.authorizeHttpRequests(registry -> {
registry.requestMatchers("/api/v1/auth/**").permitAll();
registry.requestMatchers("/api/v1/users/**").permitAll();
registry.anyRequest().authenticated();
}).formLogin(formLogin -> formLogin.permitAll())
.csrf(httpSecurityCsrfConfig -> httpSecurityCsrfConfig.disable())
.cors(httpSecurityCorsConfig -> httpSecurityCorsConfig.disable())
.sessionManagement(httpSecuritySessionConfig -> httpSecuritySessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
.httpBasic(Customizer.withDefaults())
.build();
}
@Bean
public AuthenticationProvider authenticationProvider() throws Exception {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userApplicationService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return new ProviderManager(authenticationProvider());
}
@Bean
public PasswordEncoder passwordEncoder() throws Exception {
return new BCryptPasswordEncoder();
}
}
And the method that throws exception:
public boolean isCoptchaCodeValid(CaptchaCode captchaCode) throws ValidationException {
...
}
I quick test with the below code, gives me this body:
{"now":"2024-12-20T14:53:02.339526733","name":"BAD_REQUEST","description":"uri=/backend-spring-boot/graphiql","message":"Invalid token"}
ExceptionDetails
import java.time.LocalDateTime;
public record ExceptionDetails(
LocalDateTime now,
String name,
String description,
String message) {
}
JwtAuthenticationFilter
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
@Qualifier("handlerExceptionResolver")
private HandlerExceptionResolver resolver;
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) {
try {
throw new ValidationException("Invalid token");
} catch (ValidationException e) {
resolver.resolveException(request, response, null, e);
}
}
}
ValidationException
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}
Update Added my security config (relevant parts)
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.csrf(AbstractHttpConfigurer::disable)
.cors(Customizer.withDefaults())
.formLogin(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/graphiql","/graphql").permitAll()
.requestMatchers("/error").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
.build();
}