有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我正在编写一个RESTful服务,没有用户界面,因此没有错误页面。当我得到一个过期的令牌时,我想设置一个特定的错误代码和消息,以便调用者知道它需要再次登录。(我不担心给黑客提供额外的信息,因为我只在令牌具有正确的数字签名时看到这种情况。)我试过三种不同的方法

  1. 抛出CredentialsExpiredException,它扩展了AuthenticationException。我已经安装了一个AuthenticationEntryPoint来处理异常,但是SpringSecurity向它发送了一个不同的异常。因此,无法区分自定义失败和标准身份验证拒绝
  2. 抛出一个用@ResponseStatus(HttpStatus.EXPECTATION_FAILED)注释的自定义异常。 这应该会生成一个417的错误代码,但我得到一个403。我还尝试添加一个用@ControllerAdvice注释的类,但没有效果
  3. 我在SecurityContext中设置了一个UsernamePasswordAuthenticationToken,但凭证列表为空。这将生成与任何其他故障模式具有相同403 Http状态的响应。无法指定不同的状态代码或消息

我将我的AuthenticationEntryPoint安装到我的WebSecurity配置中,如下所示:

@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进行尝试 自述。md文件解释了如何使用它,并记录了它实现的端点。它使用Java12,但代码将在Java8下编译

(我知道身份验证失败通常不会返回太多信息,以避免给黑客提供任何有用的信息,但我只想告诉用户,他们的JWT令牌已过期,他们需要重新登录。上面的测试用例不使用JWT,因为不必重现问题。)


共 (1) 个答案

  1. # 1 楼答案

    我从未找到更改HttpStatus代码的方法,但我确实找到了通知调用方令牌已过期的方法。当我检测到过期令牌时,我会在响应中添加一个指定过期令牌的头。这不完全是我想要的,但它做到了

    有一次,我能够使用这个头来更改AuthenticationEntryPoint类中的响应代码。但我又试了一次,结果没用。我不知道我改变了什么来打破这个,但这无关紧要