Reputation: 249
I was wondering if I could customize the following forbidden JSON error:
Actual Response
{
"timestamp": "2018-09-26T06:11:05.047+0000",
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/api/rest/hello/me"
}
Custom Response - I get it when the user request does not have permissions.
{
"code": 403,
"message": "Access denied by the system",
"status": "Failure"
}
My Web security class
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtTokenProvider jwtTokenProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests()//
.antMatchers("/rest/hello/signin").permitAll()//
.anyRequest().authenticated();
http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
}
Upvotes: 8
Views: 6939
Reputation: 37
add this in your controller or ExceptionHandler :
@ExceptionHandler(AccessDeniedException.class)
public @ResponseBody ResponseEntity<AuthzErrorResponse> handlerAccessDeniedException(final Exception ex,
final HttpServletRequest request, final HttpServletResponse response) {
AuthzErrorResponse authzErrorResponse = new AuthzErrorResponse();
authzErrorResponse.setMessage("Access denied");
return new ResponseEntity<>(authzErrorResponse, HttpStatus.FORBIDDEN);
}
Note:AuthzErrorResponse is my custom POJO which I want to return.
Upvotes: -1
Reputation: 417
You can create custom handler using the Jackson ObjectMapper
like this:
@Bean
public AccessDeniedHandler accessDeniedHandler() {
return (request, response, ex) -> {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
ServletOutputStream out = response.getOutputStream();
new ObjectMapper().writeValue(out, new MyCustomErrorDTO());
out.flush();
};
}
And configure your HttpSecurity
like this:
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
Also, you can try throw AuthenticationException
:
@Bean
public AuthenticationFailureHandler failureHandler() {
return (request, response, ex) -> { throw ex; };
}
And handle them in @RestControllerAdvice
:
@RestControllerAdvice
public class AdviseController {
@ExceptionHandler(AuthenticationException.class)
@ResponseStatus(HttpStatus.FORBIDDEN)
public MyCustomErrorDTO handleAuthenticationException(AuthenticationException ex) {
return new MyCustomErrorDTO();
}
}
But I'm not sure that it will work, you can check it out.
Upvotes: 5
Reputation: 1704
To display custom message i created entry point class JwtAuthenticationEntryPoint for JWT Security.
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationEntryPoint.class);
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
logger.error("Responding with unauthorized error. Message - {}", e.getMessage());
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Sorry, You're not authorized to access this resource.");
}
}
And pass as entry point To security config like,
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
.antMatchers("auth/singIn" , "auth/singUp/")
.permitAll().anyRequest().authenticated();
}
}
Or you can use @ControllerAdvice and custom exception handling to handle custom or system exception
Upvotes: 1