Spring Rest API和Swagger UI的自定义错误对象

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

我有一个Spring Boot Rest API项目,正在考虑如何更改从Spring Boot返回的默认错误对象。

UseCase:/ token api将在不进行身份验证的情况下被调用,而其他api将通过传递令牌来被调用。摇摇欲坠的UI需要用于相同的目的。错误响应需要修改为自定义对象。

例如:默认结构类似于未经授权的api请求。

{
    "timestamp": "2020-06-14T05:46:37.538+00:00",
    "status": 401,
    "error": "Unauthorized",
    "message": "Unauthorized",
    "path": "/scholarship/api/v1.0/applicant" 
}

我希望它像

{
  "status": "error",
  "message": "Unauthorised"
}

我也为该项目配置了swagger ui。

我的配置文件就是这样,它可以帮助我打开swagger-ui。 html和我也曾试图在此异常处理程序中获取未经授权的对象的句柄,但不会触发。

@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(
            new AntPathRequestMatcher("/api/**")
    );

    AuthenticationProvider provider;

    public SecurityConfig(final AuthenticationProvider authenticationProvider) {
        super();
        this.provider = authenticationProvider;
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(provider);
    }

    @Override
    public void configure(final WebSecurity webSecurity) {
        webSecurity.ignoring().antMatchers("/token/**");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
                .and()
                .authenticationProvider(provider)
                .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class)
                .authorizeRequests()
                .requestMatchers(PROTECTED_URLS)
                .authenticated()
                .and()
                .csrf().disable()
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable();
    }

    @Bean
    AuthenticationFilter authenticationFilter() throws Exception {
        log.error("in authenticationFilter");
        final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS);
        filter.setAuthenticationManager(authenticationManager());

        //filter.setAuthenticationSuccessHandler(successHandler());
        return filter;
    }


    @Autowired
    private HandlerExceptionResolver handlerExceptionResolver;

    public AuthenticationEntryPoint authenticationEntryPoint() {
        log.error("in authenticationEntryPoint");
        return new AuthenticationEntryPoint() {
            @Override
            public void commence(HttpServletRequest request, HttpServletResponse response,
                                 AuthenticationException authException) throws IOException, ServletException {
                log.error("in commence");
                try {
                    log.error(authException.getLocalizedMessage());
                    handlerExceptionResolver.resolveException(request, response, null, authException);
                } catch (RuntimeException e) {
                    throw e;
                } catch (Exception e) {
                    throw new ServletException(e);
                }
            }
        };
    }
}

或者,我有一个@ControllerAdvice来重新格式化错误对象,但它也不起作用

@ExceptionHandler(value = {InsufficientAuthenticationException.class})
    public final ResponseEntity<Object> authenticationException(InsufficientAuthenticationException ex) {
        List<String> details = new ArrayList<>();
        details.add("Authentication is required to access this resource");
        ErrorResponse error = new ErrorResponse("error", "Unauthorized", details);
        return new ResponseEntity(error, HttpStatus.FORBIDDEN);
    }

可能是配置错误?

更新:

如果更改为此选项,则在调用安全api时会得到自定义对象,但是swagger Ui无法打开,并且出现了关于swagger UI访问的自定义错误

@Override
    public void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                .anyRequest()
                .fullyAuthenticated();

        http.exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint());
    }

访问Swagger UI时出错

{"status":"error","message":"Unauthorized","errors":["Authentication is required to access this resource"]}

更新2:

更改为以下内容将打开Swagger UI,但同样,错误对象不是自定义的,然后

 @Override
    public void configure(HttpSecurity http) throws Exception {
        log.error("in configure");
        http.authenticationProvider(provider)
                .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class)
                .authorizeRequests()
                .requestMatchers(PROTECTED_URLS)
                .fullyAuthenticated();

        http.exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint());
    }
spring-boot swagger-ui swagger-2.0
1个回答
0
投票

来自Servlet过滤器的未到达控制器的异常由BasicErrorController

您需要重写BasicErrorController来更改spring抛出的默认异常主体。

如何覆盖:

@RestController
@Slf4j
public class BasicErrorControllerOverride extends AbstractErrorController {

  public BasicErrorControllerOverride(ErrorAttributes errorAttributes) {
    super(errorAttributes);
  }

  @RequestMapping
  public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
    HttpStatus status = this.getStatus(request);
    Map<String, Object> errorCustomAttribute = new HashMap<>();
    errorCustomAttribute.put("status", "error");
    errorCustomAttribute.put("message", status.name());
    return new ResponseEntity(errorCustomAttribute, status);
  }

  @Override
  public String getErrorPath() {
    return "/error";
  }
}

错误响应将如何显示

{
    "message": "UNAUTHORIZED",
    "status": "error"
}
© www.soinside.com 2019 - 2024. All rights reserved.