phenomenon
The following code is configured in websecurityconfigureradapter:
// Customize unauthorized and non-login exceptions
http.exceptionHandling()
.accessDeniedHandler(new RestAccessDeniedHandler())
.authenticationEntryPoint(new RestAuthenticationEntryPoint());
The @preauthorize annotation is added to the rest interface of the controller layer:
@PreAuthorize(value = "hasAuthority('Users.Update')")
@GetMapping("/hello")
public ResponseEntity<?> hello(@RequestParam(value = "name", required = false, defaultValue = "Tom") String name) {
return ResponseEntity.ok(RestResponse.buildResponse("Hi: " + name));
}
The provider interface/Hello reports a server 500 error and does not execute the accessdeniedhandler we set to handle exceptions with insufficient permissions.
reason
The @preauthorize annotated exception throws an accessdeniedexception, which will not be caught by the accessdeniedhandler, but by the global exception. Example code for global exception handling accessdeniedexception:
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<RestResponse<Object>> handleException(Exception exception) {
String message = exception.getLocalizedMessage();
log.error("Exception: {}", message, exception);
HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
if (exception instanceof BadCredentialsException) {
httpStatus = HttpStatus.UNAUTHORIZED;
}
if (exception instanceof HttpRequestMethodNotSupportedException) {
httpStatus = HttpStatus.METHOD_NOT_ALLOWED;
}
return RestResponse.buildError(httpStatus, message);
}
@ExceptionHandler(CommonException.class)
public ResponseEntity<RestResponse<Object>> handleException(CommonException exception) {
String message = exception.getLocalizedMessage();
log.error("CommonException:{}", message);
return RestResponse.buildError(exception.getBusinessStatus(), message);
}
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<RestResponse<Object>> handleException(AccessDeniedException exception) {
String message = exception.getLocalizedMessage();
log.error("AccessDeniedException: {}", message);
return RestResponse.buildError(HttpStatus.FORBIDDEN, Forbidden);
}
}
If it needs to be captured and processed by accessdeniedhandler, you need to write the code of websecurityconfigureradapter as follows:
http.cors().and()
.authorizeRequests().antMatchers("/hello0").permitAll()
// Note that hasRole, hasAuthority will call the set accessDeniedHandler method if an exception occurs.
.antMatchers("/hello").hasAuthority("Users.Update")
.anyRequest().authenticated();
// Customize unauthorized and non-login exceptions
http.exceptionHandling()
.accessDeniedHandler(new RestAccessDeniedHandler())
.authenticationEntryPoint(new RestAuthenticationEntryPoint());