Spring boot SpringRESTAPI和身份验证的自定义错误对象
我有一个SpringBootRESTAPI项目,我正在考虑如何更改SpringBoot返回的默认错误对象 用例:/token api将在没有身份验证的情况下调用,而其他api将通过传递令牌来调用。 swagger UI也需要用于同样的目的。 错误响应需要作为自定义对象进行修改 对于未经授权的api请求,默认结构是这样的Spring boot SpringRESTAPI和身份验证的自定义错误对象,spring-boot,swagger-ui,swagger-2.0,Spring Boot,Swagger Ui,Swagger 2.0,我有一个SpringBootRESTAPI项目,我正在考虑如何更改SpringBoot返回的默认错误对象 用例:/token api将在没有身份验证的情况下调用,而其他api将通过传递令牌来调用。 swagger UI也需要用于同样的目的。 错误响应需要作为自定义对象进行修改 对于未经授权的api请求,默认结构是这样的 { "timestamp": "2020-06-14T05:46:37.538+00:00", "status": 401, "error": "Unau
{
"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
我的配置文件是这样的,这有助于我打开大摇大摆的用户界面。html和我也尝试在这个异常处理程序中获取未经授权的abject的句柄,但它没有启动
@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);
}
访问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());
}
更新3:
核心问题在于configureHttpSecurity http方法
如果我添加以下两行,API将被验证,但错误对象是默认对象。如果我删除这些行,API将不被验证,即使您传递了令牌,它们仍然会失败,但我得到了自定义错误对象
.authenticationProvider(provider)
.addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class)
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);
/*
If you want to pull default error attributes and modify them, use this
Map<String, Object> defaultErrorAttributes = this.getErrorAttributes(request, false);
*/
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";
}
}
删除抛出新ServletException;和添加throw new insufficientAuthenticationExceptionOne.GetMessage没有帮助..仍然可以忽略SecurityConfig.java、public void configurefinal WebSecurity WebSecurity{WebSecurity.ignering.antMatchers/token/**、/swagger*/**、/v2/api docs、/webjars/**、/configuration/**;}没用,还是一样
@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);
/*
If you want to pull default error attributes and modify them, use this
Map<String, Object> defaultErrorAttributes = this.getErrorAttributes(request, false);
*/
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"
}