无法为 JWT CustomClaimVerifier 抛出自定义异常消息

Posted

技术标签:

【中文标题】无法为 JWT CustomClaimVerifier 抛出自定义异常消息【英文标题】:Cannot throw custom exception message for 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 抛出的标准异常消息。

【问题讨论】:

【参考方案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 吗?

以上是关于无法为 JWT CustomClaimVerifier 抛出自定义异常消息的主要内容,如果未能解决你的问题,请参考以下文章

将 Asp.Net Core 1 转换为 Core 2 后 Jwt 无法正常工作

Jwt 无法有效的发行者或受众

使用 Jwt 的基于令牌的身份验证无法授权

无法使用 JWT 令牌连接到 Apple App Store API

我有由 laravel 8 创建的项目,并且我将 JWT 用于我的 API,现在由于 JWT 版本我无法安装推送器

邮递员使用 JWT 进行授权调用时无法获得任何响应