Spring Security与hibernate-validator冲突:参数校验失效返回Access Denied
问题分析与解决方案
问题根源
引入spring-boot-starter-security后,Spring Security的默认异常处理机制会拦截请求流程中抛出的异常。当参数校验失败(比如@NotNull触发的校验异常)时,该异常被Security拦截,返回了"Access Denied",而非预期的校验提示信息。
解决方案
1. 全局异常处理器捕获校验异常
创建全局异常处理类,专门捕获参数校验相关异常,返回自定义响应结果:
import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import java.util.stream.Collectors; @RestControllerAdvice public class GlobalExceptionHandler { // 处理实体类参数上的@Validated校验异常 @ExceptionHandler(MethodArgumentNotValidException.class) public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { FieldError fieldError = e.getBindingResult().getFieldErrors().get(0); return Result.fail(fieldError.getDefaultMessage()); } // 处理其他类型的校验异常 @ExceptionHandler(ConstraintViolationException.class) public Result handleConstraintViolationException(ConstraintViolationException e) { String message = e.getConstraintViolations().stream() .map(ConstraintViolation::getMessage) .collect(Collectors.joining(";")); return Result.fail(message); } }
2. 调整Spring Security配置(可选)
若全局异常处理器未生效,可在Security配置中允许目标接口的匿名访问,或自定义异常处理逻辑:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth // 允许/add接口匿名访问(无需权限验证时使用) .requestMatchers("/add").permitAll() .anyRequest().authenticated() ) .exceptionHandling(ex -> ex .authenticationEntryPoint((request, response, authException) -> { // 自定义认证异常响应 response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(Result.fail("认证失败").toString()); }) ); return http.build(); } }
3. 注意事项
- 确认
@Validated注解正确标注在Controller的参数上,实体类的@NotNull等校验注解配置无误。 - 确保自定义的
Result类能正常序列化为JSON格式,保证前端可解析响应内容。
内容的提问来源于stack exchange,提问作者JiangZong6666
相关产品推荐
相关产品推荐

