Spring boot:如何自定义禁止的错误 json
Posted
技术标签:
【中文标题】Spring boot:如何自定义禁止的错误 json【英文标题】:Spring boot : How could I customize the forbidden error json 【发布时间】:2019-03-01 20:29:20 【问题描述】:我想知道是否可以自定义以下禁止的 JSON 错误:
实际反应
"timestamp": "2018-09-26T06:11:05.047+0000",
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/api/rest/hello/me"
自定义响应 - 当用户请求没有权限时我得到它。
"code": 403,
"message": "Access denied by the system",
"status": "Failure"
我的网络安全课程
@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);
【问题讨论】:
docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… 【参考方案1】:将此添加到您的控制器或 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);
注意:AuthzErrorResponse 是我要返回的自定义 POJO。
【讨论】:
【参考方案2】:您可以像这样使用Jackson ObjectMapper
创建自定义处理程序:
@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();
;
然后像这样配置你的HttpSecurity
:
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
另外,你也可以试试 throw AuthenticationException
:
@Bean
public AuthenticationFailureHandler failureHandler()
return (request, response, ex) -> throw ex; ;
并在@RestControllerAdvice
处理它们:
@RestControllerAdvice
public class AdviseController
@ExceptionHandler(AuthenticationException.class)
@ResponseStatus(HttpStatus.FORBIDDEN)
public MyCustomErrorDTO handleAuthenticationException(AuthenticationException ex)
return new MyCustomErrorDTO();
但我不确定它是否会起作用,你可以检查一下。
【讨论】:
AuthenticationFailureHandler如何配置HttpSecurity? 我已经这样指出了:http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());将用于 AccessDeniedHandler 以及当我想使用 @RestControllerAdvice 时 http 安全 AuthenticationFailureHandler 怎么样
对不起,我没有仔细阅读您的评论。您可以使用AbstractAuthenticationProcessingFilter
类的自定义扩展并将其设置为http.addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class);
很多代码不适合cmets,但我可以分享我的solution。【参考方案3】:
为了显示自定义消息,我为 JWT Security 创建了入口点类 JwtAuthenticationEntryPoint。
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.");
并作为入口点传递给安全配置,
@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();
或者您可以使用@ControllerAdvice 和自定义异常处理来处理自定义或系统异常
【讨论】:
我收到以下回复,请告知如何自定义并使其如我的问题中发布的那样“timestamp”:“2018-09-26T07:09:56.601+0000”,“status”: 403, "error": "Forbidden", "message": "对不起,您无权访问该资源。", "path": "/api/rest/hello/me" 据我所知,当用户不允许访问资源时,您想提供自定义消息,在我的示例中,我通过入口点类对其进行自定义,并给出响应消息为“抱歉,您无权访问访问此资源。” , 比如: "timestamp": 1537943752965, "status": 401, "error": "Unauthorized", "message": "Sorry, You are not authorized to access this resource.", "path": "/api /report/dateWiseQtyUsedByItemGroupAndItemReport" 我需要如下自定义消息 "code": 403, "message": "Access denied by the system", "status": "Failure" @BhartiLadumor 的答案是正确的,但目前看来,Spring 不再将 message 属性作为错误响应正文的一部分发送,因为我目前正面临这个问题。你有什么想法吗?以上是关于Spring boot:如何自定义禁止的错误 json的主要内容,如果未能解决你的问题,请参考以下文章
测试开发专题:spring-boot自定义返回参数校验错误信息