[英]Why am I obtaining this exception trying to build a JWT token? java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
I am working on a Spring Boot project implementing JWT authentication but I am finding some difficulties.我正在研究实现 JWT 身份验证的 Spring 引导项目,但我发现了一些困难。 It is based on an example found into a Udemy course that I am trying to adapt to my specific use case.
它基于在 Udemy 课程中发现的一个示例,我正试图适应我的特定用例。 It is composed by the following two microservices:
它由以下两个微服务组成:
GET-USER-WS: this is the microservice that obtains user information from the database. GET-USER-WS:这是从数据库中获取用户信息的微服务。
AuthServerJWT: this microservice calls the GET-USER-WS in order to obtain user information and build the JWT token that will be used by other microservices. AuthServerJWT:此微服务调用GET-USER-WS以获取用户信息并构建将由其他微服务使用的 JWT 令牌。
Basically this second AuthServerJWT contains the following JwtAuthenticationRestController controller class:基本上,第二个AuthServerJWT包含以下JwtAuthenticationRestController controller class:
@RestController
//@CrossOrigin(origins = "http://localhost:4200")
public class JwtAuthenticationRestController {
@Value("${sicurezza.header}")
private String tokenHeader;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
@Qualifier("customUserDetailsService")
private UserDetailsService userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationRestController.class);
@PostMapping(value = "${sicurezza.uri}")
public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtTokenRequest authenticationRequest)
throws AuthenticationException {
logger.info("Autenticazione e Generazione Token");
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
logger.warn(String.format("Token %s", token));
return ResponseEntity.ok(new JwtTokenResponse(token));
}
@RequestMapping(value = "${sicurezza.uri}", method = RequestMethod.GET)
public ResponseEntity<?> refreshAndGetAuthenticationToken(HttpServletRequest request)
throws Exception
{
String authToken = request.getHeader(tokenHeader);
if (authToken == null || authToken.length() < 7)
{
throw new Exception("Token assente o non valido!");
}
final String token = authToken.substring(7);
if (jwtTokenUtil.canTokenBeRefreshed(token))
{
String refreshedToken = jwtTokenUtil.refreshToken(token);
return ResponseEntity.ok(new JwtTokenResponse(refreshedToken));
}
else
{
return ResponseEntity.badRequest().body(null);
}
}
@ExceptionHandler({ AuthenticationException.class })
public ResponseEntity<String> handleAuthenticationException(AuthenticationException e)
{
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage());
}
private void authenticate(String username, String password)
{
Objects.requireNonNull(username);
Objects.requireNonNull(password);
try {
/// ???
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
}
catch (DisabledException e)
{
logger.warn("UTENTE DISABILITATO");
throw new AuthenticationException("UTENTE DISABILITATO", e);
}
catch (BadCredentialsException e)
{
logger.warn("CREDENZIALI NON VALIDE");
throw new AuthenticationException("CREDENZIALI NON VALIDE", e);
}
}
}
AS you can see it contains two method: one to create a brand new JWT token and the other one to refresh an existing JWT token.如您所见,它包含两种方法:一种是创建全新的 JWT 令牌,另一种是刷新现有的 JWT 令牌。 Consider the createAuthenticationToken() used to create a new token.
考虑用于创建新令牌的createAuthenticationToken() 。
At this line:在这一行:
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
it call the loadUserByUsername() method defined in my CustomUserDetailsService .它调用在我的CustomUserDetailsService中定义的loadUserByUsername()方法。 This method basically retrieve the user information calling a service of the ** GET-USER-WS and build a UserDetails object (that is a Spring Security object, this one: org.springframework.security.core.userdetails.UserDetails ).
这个方法基本上是调用** GET-USER-WS的一个服务来检索用户信息,并建立一个UserDetails object(即一个Spring安全object),这个: userdetails.spring.frameworkDetail.core.userdetails.spring.framework 。
This is the code of this method:这是此方法的代码:
@Override
public UserDetails loadUserByUsername(String UserId) throws UsernameNotFoundException {
String ErrMsg = "";
if (UserId == null || UserId.length() < 2) {
ErrMsg = "Nome utente assente o non valido";
logger.warn(ErrMsg);
throw new UsernameNotFoundException(ErrMsg);
}
User user = this.GetHttpValue(UserId);
if (user == null) {
ErrMsg = String.format("User %s not found!!", UserId);
logger.warn(ErrMsg);
throw new UsernameNotFoundException(ErrMsg);
}
UserBuilder builder = null;
builder = org.springframework.security.core.userdetails.User.withUsername(Integer.toString(user.getId()));
builder.password(user.getPswd());
String[] operations = user.getUserTypes().stream()
.map(UserType::getOperations)
.flatMap(Set::stream)
.map(Operation::getName)
.distinct()
.toArray(String[]::new);
builder.authorities(operations);
return builder.build();
}
This line simply execute the GetHttpValue() method used to perform the call with the RestTemplate in order to retrieve an User object containing the details of the user:此行仅执行GetHttpValue()方法,该方法用于使用 RestTemplate 执行调用,以检索包含用户详细信息的User object:
User user = this.GetHttpValue(UserId);
So, come back to the first createAuthenticationToken() of the previous JwtAuthenticationRestController controller class.所以,回到前面的JwtAuthenticationRestController controller class的第一个createAuthenticationToken() 。 My problem is that it retrieve this UserDetails userDetails object, at this line:
我的问题是它在这一行检索了这个UserDetails userDetails object:
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
using the deubugger this is the content of my userDetails instance:使用调试器这是我的userDetails实例的内容:
org.springframework.security.core.userdetails.User [Username=50, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ADMIN]]
it seems to me correct (except the Username field that contains the ID of the user and not the username...I will change in a second time, it should not be the problem).在我看来是正确的(除了包含用户 ID 而不是用户名的用户名字段......我将在第二次更改,这应该不是问题)。
Then it perform this line in order to generate the JWT token starting from this userDetails object:然后它执行此行以便从这个userDetails object 开始生成 JWT 令牌:
final String token = jwtTokenUtil.generateToken(userDetails);
This is the code of the generateToken() method defined into a class named JwtTokenUtil :这是定义在名为JwtTokenUtil的 class 中的generateToken()方法的代码:
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails);
}
It first create an empty HashMap and then call the doGenerateToken() , this is the code:它首先创建一个空的 HashMap 然后调用doGenerateToken() ,这是代码:
private String doGenerateToken(Map<String, Object> claims, UserDetails userDetails) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.claim("authorities", userDetails.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
.setIssuedAt(createdDate)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes())
.compact();
}
It correctly create the expirationDate date.它正确地创建了expireDate日期。 Then at the end it throws the following exception (using the deubbugger it seems to me that it is thrown on the compact() execution): The problem is that when this line is executed I am obtaining the following exception:
然后在最后它抛出以下异常(使用调试器在我看来它是在compact()执行时抛出的):问题是当执行此行时,我得到以下异常:
java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
at io.jsonwebtoken.impl.Base64Codec.encode(Base64Codec.java:21) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.Base64UrlCodec.encode(Base64UrlCodec.java:22) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.DefaultJwtBuilder.base64UrlEncode(DefaultJwtBuilder.java:349) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.DefaultJwtBuilder.compact(DefaultJwtBuilder.java:295) ~[jjwt-0.9.1.jar:0.9.1]
at com.easydefi.authserverjwt.security.JwtTokenUtil.doGenerateToken(JwtTokenUtil.java:87) ~[classes/:na]
at com.easydefi.authserverjwt.security.JwtTokenUtil.generateToken(JwtTokenUtil.java:72) ~[classes/:na]
at com.easydefi.authserverjwt.controller.JwtAuthenticationRestController.createAuthenticationToken(JwtAuthenticationRestController.java:60) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.12.jar:5.3.12]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.12.jar:5.3.12]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.12.jar:5.3.12]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.12.jar:5.3.12]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.12.jar:5.3.12]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.12.jar:5.3.12]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.12.jar:5.3.12]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.12.jar:5.3.12]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) ~[tomcat-embed-core-9.0.54.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.12.jar:5.3.12]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.54.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:204) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.12.jar:5.3.12]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at java.base/java.lang.Thread.run(Thread.java:831) ~[na:na]
Why?为什么? What am I missing?
我错过了什么? How can I try to solve this issue?
我该如何尝试解决这个问题?
I don't know why I am facing this problem, when I run the code in postgres it works fine but I get thiss error with cassandra.我不知道为什么我会遇到这个问题,当我在 postgres 中运行代码时它工作正常,但是我收到 cassandra 的错误。
I have just added those into my pom.xml我刚刚将这些添加到我的 pom.xml
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.5-b10</version>
</dependency>
I got them from here: Include JAXB using Maven我从这里得到它们: 使用 Maven 包括 JAXB
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.