You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成JWT认证登录失败,报NoClassDefFoundError错误

Spring Boot JWT登录失败排查:NoClassDefFoundError: javax/xml/bind/DatatypeConverter

问题现象

在Spring Boot中实现JWT身份认证时,登录功能失败,抛出以下错误日志:

2024-02-29T12:22:12.726+05:30 ERROR 3552 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter] with root cause
2024-02-29T12:22:12.735+05:30 DEBUG 3552 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing POST /error2024-02-29T12:22:12.735+05:30 DEBUG 3552 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext

核心代码

JWT认证过滤器

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenHelper jwtTokenHelper;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    String requestToken = request.getHeader("Authorization");
    String username = null;
    String token = null;
    if (requestToken != null && requestToken.startsWith("Bearer")) {
         token = requestToken.substring(7);
         try{username=this.jwtTokenHelper.getUsernameFromToken(token);}
         catch (IllegalArgumentException e){System.out.println("Unable to get jwt token");}
         catch(ExpiredJwtException e){System.out.println("Jwt token has expired");}
         catch (MalformedJwtException e){System.out.println("Invalid jwt");}
    }
    else{System.out.println(" Jwt token does not begin with Bearer");}

    if (username != null && SecurityContextHolder.getContext().getAuthentication()==null){
        UserDetails userDetails =this.userDetailsService.loadUserByUsername(username);
        if(this.jwtTokenHelper.validateToken(token,userDetails)){
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
            usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        }
        else{
            System.out.println("Invalid jwt");}
    }
    else{

    }
    filterChain.doFilter(request,response);
}}

认证控制器

@RestController
@RequestMapping("api/v1/auth")
public class AuthController {
@Autowired
private JwtTokenHelper jwtTokenHelper;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
public AuthenticationManager authenticationManager;

@Autowired
private UserService userService;

@PostMapping("/login")
public ResponseEntity<JwtAuthResponse> createToken(@RequestBody JwtAuthRequest request) throws Exception{
    this.authenticate(request.getUsername(),request.getPassword());
    UserDetails userDetails = this.userDetailsService.loadUserByUsername(request.getUsername());
    String token = this.jwtTokenHelper.generateToken(userDetails);
    JwtAuthResponse response = new JwtAuthResponse();
    response.setToken(token);
    return new ResponseEntity<JwtAuthResponse>(response, HttpStatus.OK);
}

private void authenticate(String username, String password) throws  Exception{
    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,password);
   try{
       authenticationManager.authenticate(authenticationToken);
   }catch (BadCredentialsException e){
       System.out.println("Invalid Details");
       throw new ApiException("Invalid Username or Password");
   }
}

@PostMapping("/register")
public ResponseEntity<UserDto> regidterUser(@RequestBody UserDto userDto){
    UserDto registerdUser = this.userService.registerNewUser(userDto);
    return new ResponseEntity<UserDto>(registerdUser,HttpStatus.CREATED);
}}

配置类

@Configuration
class MyConfig {
@Autowired
UserRepo userRepo;
@Bean
public DaoAuthenticationProvider authProvider() {
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    provider.setPasswordEncoder(passwordEncoder());
    provider.setUserDetailsService(userDetailsService());
    return provider;
}

@Bean
public UserDetailsService userDetailsService() {
    return new UserDetailsService() {
        @Override
        public UserDetails loadUserByUsername(String username) {
            return userRepo.findByEmail(username).orElseThrow(()-> new ResourceNotFoundException("User","email:"+username,0));
        }
    };
}
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration builder) throws Exception {
    return builder.getAuthenticationManager();
}}

安全配置类

@Configuration
 @EnableWebSecurity
 @EnableWebMvc
public class SecurityConfig{

public static final String[] PUBLIC_URLS={
        "api/v1/auth/**",
        "/v3/api-docs",
        "/v2/api-docs",
        "/swagger-resources/**",
        "/swagger-ui/**",
        "/webjars/**"

};

@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;

@Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests((authz)-> authz
            .requestMatchers(PUBLIC_URLS).permitAll()
            .requestMatchers(HttpMethod.GET).permitAll()
            .anyRequest()
            .authenticated())
            .exceptionHandling(ex -> ex.authenticationEntryPoint(this.jwtAuthenticationEntryPoint))
            .sessionManagement(session->session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

   http
           .addFilterBefore( this.jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

   return http.build();
}}

错误原因分析

javax.xml.bind.DatatypeConverter是JDK 8及以前的标准库类,但从JDK 9开始,JAXB模块被移除出默认类路径(转为可选模块)。如果你的Spring Boot项目使用JDK 9+,且依赖的JWT库(如旧版本jjwt)仍依赖该类,就会触发NoClassDefFoundError。

常见场景是使用了io.jsonwebtoken:jjwt:0.9.1这类旧版JJWT,它们依赖JAXB的DatatypeConverter处理Base64编解码。

解决方案

方案1:升级JJWT到最新稳定版

新版本JJWT已移除对JAXB的依赖,改用JDK自带Base64工具类或内置实现,推荐升级到0.11.5及以上版本:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

注意:升级后需检查JwtTokenHelper中的代码是否适配新版本API(如JWT创建、解析方法的变化)。

方案2:添加JAXB依赖(仅兼容旧版JJWT,不推荐长期使用)

若无法升级JJWT,可手动添加JAXB依赖让JDK 9+找到缺失类:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0.1</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.3</version>
</dependency>

内容的提问来源于stack exchange,提问作者Jaydeepsinh Parmar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 23:32:06