PreAuthorize错误处理

时间:2015-02-09 13:14:15

标签: spring spring-security spring-boot spring-annotations spring-security-oauth2

我正在使用Spring Oauth2Spring Pre-post Annotations使用Spring-boot

我有一个服务类MyServiceMyService方法之一是:

@PreAuthorize("#id.equals(authentication.principal.id)")
public SomeResponse getExampleResponse(String id){...}

我能以某种方式控制调用者控制器返回的json吗?

默认返回的json是:

{error : "access_denied" , error_message: ".."}

我希望能够控制error_message参数。我正在寻找类似的东西:

@PreAuthorize(value ="#id.equals(authentication.principal.id)", onError ="throw new SomeException("bad params")")
public SomeResponse getExampleResponse(String id){...}

我想到的一种方法是使用ExceptionHandler

@ExceptionHandler(AccessDeniedException.class)
public Response handleAccessDeniedException(Exception ex, HttpServletRequest request){
    ...
}

但我无法控制异常的message。而且我不能确定将来的版本中会抛出这个Exception

3 个答案:

答案 0 :(得分:9)

关于错误处理的Spring Boot文档:http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling。一种控制JSON的方法是添加@Bean类型ErrorAttributes

@Bean
ErrorAttributes errorAttributes() {
    return new MyErrorAttributes();
}

答案 1 :(得分:5)

实施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将是您自己的POJO /模型类,您可以控制 并在“资源服务器配置”中添加该访问被拒绝的处理程序

`

@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());
    }

`

答案 2 :(得分:1)

当我实现AccessDeniedHandler时,它对我不起作用。所以我在AuthenticationEntryPoint内部创建了一个ExceptionHandler函数,并将该类标记为 @ControllerAdvice。

请在下面找到代码

@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);
}}`