Reputation: 12977
I'm using Spring Oauth2
and Spring Pre-post Annotations
With Spring-boot
I Have a service class MyService
. one of MyService
methods is:
@PreAuthorize("#id.equals(authentication.principal.id)")
public SomeResponse getExampleResponse(String id){...}
can i control in some manner the json that is returned by the caller Controller?
the json that is returned by default is:
{error : "access_denied" , error_message: ".."}
I Want to be able to control the error_message
param. I'm looking for something similar to:
@PreAuthorize(value ="#id.equals(authentication.principal.id)", onError ="throw new SomeException("bad params")")
public SomeResponse getExampleResponse(String id){...}
One way i thought of doing it is by Using ExceptionHandler
@ExceptionHandler(AccessDeniedException.class)
public Response handleAccessDeniedException(Exception ex, HttpServletRequest request){
...
}
but i can't control the message
of the exception. and also i can't be sure that this Exception
will be thrown in future releases
Upvotes: 31
Views: 25982
Reputation: 68
In my case, I use ExceptionHandler
to handle all Exceptions. However, when I debug application I realise that wrong Exception class was imported. Make sure you import correct Exception class.
// First time I import
import java.nio.file.AccessDeniedHandler;
// Correct import
import org.springframework.security.access.AccessDeniedException;
Upvotes: 0
Reputation: 1736
It was not working for me when I implemented AccessDeniedHandler. So I created a ExceptionHandler function inside AuthenticationEntryPoint and marked the class as @ControllerAdvice.
Please find the code below
@ControllerAdvice
@Component
public class EmrExceptionHandler implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(EmrExceptionHandler.class);
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AuthenticationException authException) throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.getWriter().write(convertObjectToJson(new ErrorResponse(ResponseMessages.NOT_AUTHORIZED)));
}
@ExceptionHandler(value = {AccessDeniedException.class})
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AccessDeniedException accessDeniedException) throws IOException {
logger.error("AccessDenied error: {}", accessDeniedException.getMessage());
httpServletResponse.setStatus(HttpStatus.FORBIDDEN.value());
httpServletResponse.getWriter().write(convertObjectToJson(new ErrorResponse(ResponseMessages.NOT_PERMITTED)));
}
public String convertObjectToJson(Object object) throws JsonProcessingException {
if (object == null) {
return null;
}
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(object);
}
}
Upvotes: 3
Reputation: 426
Implement AccessDeniedHandler
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
try {
ObjectMapper mapper = new ObjectMapper();
SomeJsonModel jsonResponse =new SomeJsonModel();
mapper.writeValue(response.getOutputStream(), jsonResponse);
} catch (Exception e) {
throw new ServletException();
}
}
SomeJsonModel will be your own POJO/model class which you can control And add that access denied handler in Resource Server Configuration
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers(SECURED_PATTERN).and().authorizeRequests()
.antMatchers(HttpMethod.POST,SECURED_PATTERN).access(SECURED_WRITE_SCOPE)
.anyRequest().access(SECURED_READ_SCOPE).and()
.exceptionHandling().authenticationEntryPoint(newAuthExceptionEntryPoint())
.accessDeniedHandler(new MyAccessDeniedHandler());
}
Upvotes: 9
Reputation: 58094
Spring Boot docs on error handling: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling. One way you can control the JSON is by adding a @Bean
of type ErrorAttributes
.
@Bean
ErrorAttributes errorAttributes() {
return new MyErrorAttributes();
}
Upvotes: 10