预授权错误处理

问题描述 投票:0回答:4

我正在使用

Spring Oauth2
Spring Pre-post Annotations
Spring-boot

我有服务班

MyService
MyService
方法之一是:

@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
是否会在未来的版本中被抛出

spring spring-security spring-boot spring-annotations spring-security-oauth2
4个回答
10
投票

有关错误处理的 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();
}

8
投票

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

3
投票

当我实现 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);
    }
}

0
投票

就我而言,我使用

ExceptionHandler
来处理所有异常。但是,当我调试应用程序时,我意识到导入了错误的 Exception 类。确保导入正确的异常类。

// First time I import
import java.nio.file.AccessDeniedHandler;

// Correct import
import org.springframework.security.access.AccessDeniedException;
© www.soinside.com 2019 - 2024. All rights reserved.