java—如何在SpringSecurity中为特殊情况的身份验证失败定制http状态代码?

toe95027  于 2021-07-23  发布在  Java
关注(0)|答案(1)|浏览(289)

我正在编写一个restful服务,没有用户界面,因此没有错误页。当我得到一个过期的令牌时,我想设置一个特定的错误代码和消息,以便调用者知道它需要再次登录(我不担心给黑客提供额外的信息,因为我只在令牌具有正确的数字签名时才会看到这种情况。)我尝试了三种不同的方法。
抛出credentialsexpiredexception,它扩展authenticationexception。我安装了一个 AuthenticationEntryPoint 但Spring Security 会向它发送一个不同的异常。因此,无法区分自定义失败和标准身份验证拒绝。
抛出一个自定义异常,用 @ResponseStatus(HttpStatus.EXPECTATION_FAILED) . 这应该会产生一个错误代码417,但我得到一个403禁止。我还尝试添加一个用 @ControllerAdvice ,但这没有效果。
我设置了一个 UsernamePasswordAuthenticationToken 进入 SecurityContext ,但凭据列表为空。这将生成与任何其他故障模式具有相同403 http状态的响应。无法指定其他状态代码或消息。
我安装我的 AuthenticationEntryPoint 我的网络安全配置如下:

@SuppressWarnings("HardcodedFileSeparator")
@Override
protected void configure(final HttpSecurity http) throws Exception {
  log.trace("Configuring WebSecurityConfig");

  /* The /view/**path requires no authentication. The others start with /admin, and require the ADMIN role. */
  http
      .csrf()
        .disable()
      .cors()
        .disable()
      .formLogin()
        .disable()
      .authorizeRequests()
        .antMatchers("/admin/**")
          .hasRole("ADMIN")
        .antMatchers("/view/**")
          .permitAll()
      .anyRequest()
        .authenticated()
      .and()
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      .and()
      .exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint)
      .and()
        .addFilterBefore(requestFilter, UsernamePasswordAuthenticationFilter.class)
  ;
}

我在上面最后一行中安装的requestfilter是抛出异常的地方,我认为异常会被发送到 AuthenticationEntryPoint .
我不知道为什么 @ResponseStatus 注解不起作用。我不知道如何在SpringSecurity中设置特定的错误代码。
我已经创建了一个最小的可复制的测试用例,您可以在https://github.com/swingguy1024/securityquestion readme.md文件解释了如何使用它并记录了它实现的端点。它使用Java12,但代码将在Java8下编译。
(我知道身份验证失败通常不应该返回太多信息,以避免向黑客提供任何有用的信息,但我只想告诉用户,他们的jwt令牌已过期,他们需要重新登录。上面的测试用例没有使用jwt,因为没有必要重现问题。)

js4nwp54

js4nwp541#

我从未找到更改httpstatus代码的方法,但我确实找到了通知调用方令牌已过期的方法。当我检测到过期令牌时,我会在响应中添加一个指定过期令牌的头。这不完全是我想要的,但它确实奏效了。
有一次,我可以使用这个头来更改authenticationentrypoint类中的响应代码。但我又试了一次,结果没用。我不知道我换了什么来打破这个,但没关系。

相关问题