【问题标题】:Cannot throw custom exception message for JWT CustomClaimVerifier无法为 JWT CustomClaimVerifier 抛出自定义异常消息
【发布时间】:2019-12-06 23:12:30
【问题描述】:

我正在尝试使用 Spring Boot 2.1 提供的 JwtClaimsSetVerifier 验证 JWT 令牌中的声明。问题是Spring总是抛出一个带有默认异常消息的异常:

{
    "error": "invalid_token",
    "error_description": "Cannot convert access token to JSON"
}

即使我创建了扩展 ClientAuthenticationException 的自定义异常,我也会收到相同的异常消息。

当 JWT 声明验证失败时,我想修改异常消息。这是我的配置类:

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceserverConfig extends ResourceServerConfigurerAdapter{

    @Autowired
    private DataSource dataSource;

     @Override
       public void configure(HttpSecurity http) throws Exception {
          http.authorizeRequests().anyRequest().permitAll().and()
          .exceptionHandling().accessDeniedHandler(new CustomAccessDeniedHandler());

       }


     @Bean
     public DataSource getDataSource() {

            return dataSource;
        }

     @Bean
     public JwtAccessTokenConverter accessTokenConverter() {
          JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
          converter.setSigningKey("qwerty123");
          converter.setJwtClaimsSetVerifier(jwtClaimsSetVerifier());
          return converter;
     }

     @Bean
      public AuthenticationFailureHandler authenticationFailureHandler()
      {
        return new RestAuthenticationFailureHandler();
      }

     @Bean
       public JwtClaimsSetVerifier jwtClaimsSetVerifier() {
          return new DelegatingJwtClaimsSetVerifier(Arrays.asList(customJwtClaimVerifier()));
       }

     @Bean
       public JwtClaimsSetVerifier customJwtClaimVerifier() {
          return new CustomClaimVerifier();
       }

     @Override
       public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
          TokenStore tokenStoreRes = new JdbcTokenStore(dataSource);
          resources.resourceId("RESOURCE").tokenStore(tokenStoreRes);
       }

       @Bean
       @Primary
       public DefaultTokenServices tokenJWTServices() {
          DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
          TokenStore tokenStoreRes = new JwtTokenStore(accessTokenConverter());
          defaultTokenServices.setTokenStore(tokenStoreRes);
          defaultTokenServices.setSupportRefreshToken(true);
          return defaultTokenServices;
       }


}

这是我的JWTClaimVerifier 课程:

public class CustomClaimVerifier implements JwtClaimsSetVerifier{

    @Autowired
    HttpServletRequest request;

    @Override
    public void verify(Map<String, Object> claims) throws InvalidTokenException {
        try {
            JsonParser parser = new JsonParser();
            String json = new Gson().toJson(claims.get("userdetails"));
            JsonElement menu = parser.parse(json);
            String menuList = menu.getAsJsonObject().get("menu").getAsString();
            boolean isMenuAccessible = validateAccessForMenu(request.getHeader("menuClicked"), menuList);
            if(!isMenuAccessible) {
                throw new InvalidTokenException("Invalid Permissions");
            }
        } catch (Exception e) {
            throw new InvalidTokenException(e.getMessage());
        }
    }
}

当 JWT 声明验证失败时,我想要一个带有自定义异常消息的异常,但我得到的只是 Spring Security 抛出的标准异常消息。

【问题讨论】:

    标签: spring spring-boot spring-security jwt spring-security-oauth2


    【解决方案1】:

    当 JWT 声明验证失败时,我想修改异常消息。

    但您确实收到了自定义异常消息。

    您看到的消息是因为其他事情,在声明可以被验证之前的事情,失败了。

    如果您查看JwtAccessTokenConverter 中的decode(String) 方法,您会看到您的JwtClaimsSetVerifier 实现是在令牌字符串被调用之后调用的解码为 Jwt 并且声明已被解析。如果在解码令牌时抛出异常,您的 CustomClaimVerifier 将没有机会覆盖该异常。

    是否要覆盖解码失败时抛出的默认异常信息?

    很遗憾,似乎没有一种直接的方式来提供您自己的信息。也许您可以将JwtAccessTokenConverter 子类化并用您自己的替换每个InvalidTokenException

    public class CustomJwtAccessTokenConverter extends JwtAccessTokenConverter {
    
        @Override
        protected Map<String, Object> decode(String token) {
            Map<String, Object> pieces = null;
    
            try {
                pieces = super.decode(token);
            } catch(InvalidTokenException ex) {
                throw new InvalidTokenException("MY CUSTOM MESSAGE");
            }
    
            return pieces;
        }
    }
    

    【讨论】:

    • 我确实看到了源代码,因为我在解码内部调用的 verify 方法中抛出异常,所以抛出异常。 spring 是否提供了其他方法来验证 JWT cliams。我用谷歌搜索了一遍,这就是我可以使用 spring 找到的。有其他使用 JJWT 的东西,但我不想使用它
    • 我不知道
    • 你检查过 Spring Security 5 吗?
    猜你喜欢
    • 1970-01-01
    • 2017-02-28
    • 2011-09-18
    • 2018-05-30
    • 2011-10-06
    • 2023-03-05
    • 1970-01-01
    • 2011-05-30
    相关资源
    最近更新 更多