java—是否可以使用jwt身份验证进行自定义错误响应?

wpcxdonn  于 2021-08-20  发布在  Java
关注(0)|答案(1)|浏览(420)

我开始基于自定义错误响应构建我的项目,以便只发送包含我需要的字段的json正文。因为这个原因,我有一个

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler

它捕获所有异常并返回具有自定义错误体的responseentity。
我有一个postgres数据库,可以保存用户。目前我有/sign、/signup和/profile端点。我想使用jwt身份验证。我使用了这个github repo,当我在/signin端点上发送用户凭据时,我可以获得令牌。
问题出在这里。阅读jwttokenfilter.java的这一部分

protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
    String token = jwtTokenProvider.resolveToken(httpServletRequest);
    try {
      if (token != null && jwtTokenProvider.validateToken(token)) {
        Authentication auth = jwtTokenProvider.getAuthentication(token);
        SecurityContextHolder.getContext().setAuthentication(auth);
      }
    } catch (CustomException ex) {
      //this is very important, since it guarantees the user is not authenticated at all
      SecurityContextHolder.clearContext();
      httpServletResponse.sendError(ex.getHttpStatus().value(), ex.getMessage());
      return;
    }

    filterChain.doFilter(httpServletRequest, httpServletResponse);
  }

假设我想注册一个新用户。然后,我的请求头将没有令牌(令牌为null),程序将执行 filterChain.doFilter(httpServletRequest, httpServletResponse); . 这项工作很好,用户注册了,我得到了 201 我的控制器在成功注册后返回。然而,假设我再次在没有令牌的/profile端点发出get请求。这也将执行filterchain.dofilter。然而,这次spring将以非定制的方式响应 403 错误响应。我找不到在restcontrollerhandler上捕获异常的方法,因为spring为我处理它。
而且,当我在内部抛出异常时 doFilterInternal ,该异常将不再由我的globalhandler处理,由spring处理。

vdgimpew

vdgimpew1#

必须添加自定义authenticationfailurehandler

public class CustomAuthenticationFailureHandler 
  implements AuthenticationFailureHandler {

private ObjectMapper objectMapper = new ObjectMapper();

@Override
public void onAuthenticationFailure(
  HttpServletRequest request,
  HttpServletResponse response,
  AuthenticationException exception) 
  throws IOException, ServletException {

    response.setStatus(HttpStatus.UNAUTHORIZED.value());
    Map<String, Object> data = new HashMap<>();
    data.put(
      "timestamp", 
      Calendar.getInstance().getTime());
    data.put(
      "exception", 
      exception.getMessage());

    response.getOutputStream()
      .println(objectMapper.writeValueAsString(data));
 }
}

然后在这里进行配置

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(AuthenticationManagerBuilder auth) 
  throws Exception {
    auth.inMemoryAuthentication()
      .withUser("user1").password(passwordEncoder.encode("user1Pass")).roles("USER");
}

@Override
protected void configure(HttpSecurity http) 
  throws Exception {
    http
      .authorizeRequests()
      .anyRequest()
      .authenticated()
      .and()
      .formLogin()
      .failureHandler(authenticationFailureHandler());
}

@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
    return new CustomAuthenticationFailureHandler();
}
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
 }
}

相关问题