Spring 无法为JWT CustomClaimVerifier引发自定义异常消息

Spring 无法为JWT CustomClaimVerifier引发自定义异常消息,spring,spring-boot,spring-security,jwt,spring-security-oauth2,Spring,Spring Boot,Spring Security,Jwt,Spring Security Oauth2,我试图使用SpringBoot2.1提供的JwtClaimsSetVerifier验证JWT令牌中的声明。问题在于Spring总是抛出一个带有默认异常消息的异常: { "error": "invalid_token", "error_description": "Cannot convert access token to JSON" } 即使我创建了一个扩展ClientAuthenticationException的自定义异常,我也会收到相同的异常消息 当JWT声明验证失败时

我试图使用SpringBoot2.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());
        }
    }
}
公共类CustomClaimVerifier实现JwtClaimsSetVerifier{
@自动连线
HttpServletRequest请求;
@凌驾
public void verify(映射声明)引发InvalidTokenException{
试一试{
JsonParser=新的JsonParser();
字符串json=new Gson().toJson(claims.get(“userdetails”);
JsonElement menu=parser.parse(json);
字符串menuList=menu.getAsJsonObject().get(“menu”).getAsString();
布尔值isMenuAccessible=ValidateAccessFormMenu(request.getHeader(“menuClicked”),menuList;
如果(!ismenu可访问){
抛出新的InvalidTokenException(“无效权限”);
}
}捕获(例外e){
抛出新的InvalidTokenException(例如getMessage());
}
}
}
当JWT声明验证失败时,我希望自定义异常消息出现异常,但我得到的只是Spring Security抛出的标准异常消息

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

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

你看到的信息是因为在索赔被证实之前的其他事情失败了

如果您在
JwtAccessTokenConverter
中检查
decode(String)
方法,您将看到
jwtclaimsetverifier
的实现在将令牌字符串解码为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;
    }
}
公共类CustomJwtAccessTokenConverter扩展了JwtAccessTokenConverter{
@凌驾
受保护地图解码(字符串标记){
图块=空;
试一试{
片段=超级解码(令牌);
}捕获(InvalidTokenException-ex){
抛出新的InvalidTokenException(“我的自定义消息”);
}
返回件;
}
}
当JWT声明验证失败时,我想修改异常消息

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

你看到的信息是因为在索赔被证实之前的其他事情失败了

如果您在
JwtAccessTokenConverter
中检查
decode(String)
方法,您将看到
jwtclaimsetverifier
的实现在将令牌字符串解码为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;
    }
}
公共类CustomJwtAccessTokenConverter扩展了JwtAccessTokenConverter{
@凌驾
受保护地图解码(字符串标记){
图块=空;
试一试{
片段=超级解码(令牌);
}捕获(InvalidTokenException-ex){
抛出新的InvalidTokenException(“我的自定义消息”);
}
返回件;
}
}

我确实看到了源代码,因为我在解码内部调用的verify方法上抛出了一个异常,所以抛出了异常。spring是否提供了任何其他方法来验证JWT客户端。我搜索了所有的地方,这就是我用spring可以找到的。使用JJWT的其他东西也存在,但我不想使用它。我不知道您是否签出了SpringSecurity5?我确实看到了源代码,因为我在验证方法中抛出了一个异常,该方法在解码内部调用,因此引发了异常。spring是否提供了任何其他方法来验证JWT客户端。我搜索了所有的地方,这就是我用spring可以找到的。还有其他使用JJWT的东西,但我不想使用它。我不知道你们有并没有检查过SpringSecurity5?