강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

cloverj0님의 프로필 이미지
cloverj0

작성한 질문수

Spring Boot를 활용하여 채팅 플랫폼 만들어보기

서비스 구동하며 테스트와 디버깅하기 - 2

JWTDecodeException 에러가 나옵니다.

해결된 질문

작성

·

78

·

수정됨

0

알려주신데로 UserControllerV1.java에 어노테이션 추가하고 재기동한 뒤 검색 했는데...로그에

com.auth0.jwt.exceptions.JWTDecodeException: The token was expected to have 3 parts, but got 1.

이런 에러가 나옵니다.ㅠㅠ

개발자 도구에는 아래와 같은 에러가 나옵니다.

image.png

 

UserControllerV1.java는 이렇게 작성되어 있습니다.

image.png

 

어떤 부분을 더 확인해야 하는지, 어떤 부분이 문제 인건지 확인 부탁드립니다.ㅠㅠ

 

**추가로 에러내용 전체입니다.

com.auth0.jwt.exceptions.JWTDecodeException: The token was expected to have 3 parts, but got 1.

at com.auth0.jwt.TokenUtils.splitToken(TokenUtils.java:21)

~[java-jwt-3.12.0.jar!/:3.12.0]

at com.auth0.jwt.JWTDecoder.<init>(JWTDecoder.java:36) ~[java-jwt-3.12.0.jar!/:3.12.0]

at com.auth0.jwt.JWTDecoder.<init>(JWTDecoder.java:32) ~[java-jwt-3.12.0.jar!/:3.12.0]

at com.auth0.jwt.JWT.decode(JWT.java:45) ~[java-jwt-3.12.0.jar!/:3.12.0]

at com.example.demo.security.JWTProvider.decodedJWT(JWTProvider.java:109) ~[!/:0.0.1-SNAPSHOT]

at com.example.demo.security.JWTProvider.getUserFromToken(JWTProvider.java:123) ~[!/:0.0.1-SNAPSHOT]

at com.example.demo.domain.user.controller.UserControllerV1.searchUser(UserControllerV1.java:43) ~[!/:0.0.1-SNAPSHOT]

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[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:568) ~[na:na]

at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.13.jar!/:6.1.13]

at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.13.jar!/:6.1.13]

at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.13.jar!/:6.1.13]

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.13.jar!/:6.1.13]

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.13.jar!/:6.1.13]

at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.13.jar!/:6.1.13]

at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.13.jar!/:6.1.13]

at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.13.jar!/:6.1.13]

at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.13.jar!/:6.1.13]

at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.1.13.jar!/:6.1.13]

at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.13.jar!/:6.1.13]

at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.30.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.13.jar!/:6.1.13]

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.13.jar!/:6.1.13]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.13.jar!/:6.1.13]

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.13.jar!/:6.1.13]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.13.jar!/:6.1.13]

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.13.jar!/:6.1.13]

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:384) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.30.jar!/:na]

at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.30.jar!/:na]

at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

답변 2

0

Hong님의 프로필 이미지
Hong
지식공유자

안녕하세요 cloverj0님 질문 남겨주셔서 감사합니다.

 

전반적인 에러 문구를 보았을 떄, Authorization 헤더에 값이 이상한거 같습니다.

 

다음과 같은 부분을 확인해보시면 좋을 꺼 같아요.

  1. API에 들어오는 헤더 값

  2. 요청을 하는 API 소스

  3. JwtProvider에서 token을 핸들링 하는 소스

 

1번 과정에 대해서는 기본적인 로그를 찍어보시고 확인해보시면 좋을 꺼 같고

2,3번 과정에 대해서는 소스 제공해 주시면 확인해보도록 하겠습니다.

 

감사합니다!

cloverj0님의 프로필 이미지
cloverj0
질문자

안녕하세요!

 

1번에 알려주신 헤더 값을 찍어보니

=========authString=============Bearer token (헤더부분)

=========token=============token

이렇게 값이 나옵니다! 이 두 값이 나오는 게 맞을까요?

 

소스는

https://github.com/hyunjin-joo/inf_study.git

이곳에 src 폴더를 업로드 해놓았습니다!! 더 확인해 봐야 할 폴더가 있으시면 말씀 부탁드립니다:)

(또는 https://drive.google.com/drive/folders/1Yi7cJpnW360yN9kCoWfTWGe7jYVCEHpb?usp=sharing

여기에서 확인 부탁드립니다! - 몇 개의 파일은 다 업로드가 되지 않아 더 확인해야 할 파일이 있으면 말씀 부탁드립니다!)

 

항상 친절히 답 주셔서 감사합니다!

 

 

Hong님의 프로필 이미지
Hong
지식공유자

음 로그상 저렇게 노출이 된다면, 기본적인 값은 정확하게 들어온거 같습니다.

하지만 에러구문 상에서, JWTDecodeException이 발생하고, 에러 문구는 다음과 같이 발생하고 있습니다.

  • The token was expected to have 3 parts, but got 1.

이 에러는 기본적으로 JWT는 3가지 파트로 구성이 되어 있는데, 디코딩을 진행하니 한가지 파트로만 진행이 되어 있다는 에러 입니다.

 

즉 Token을 잘못생성하여 값을 전달한게 아닐까 싶습니다.

 

우선적으로 사용하시는 Token을 다음과 같은 사이트에서 확인하시고 3가지 파트로 구성이 되어 있는지 확인해보시면 좋을 꺼 같습니다.

 

그리고 만약 문제가 있다면, 토큰을 생성하는 부분이나, Clinet에서 값을 잘라서 보내는지를 확인해봐야 할 꺼 같습니다.

cloverj0님의 프로필 이미지
cloverj0
질문자

안녕하세요!

npm run dev 하는 쪽의 로그를 보니

⨯ src\components\chat\chat-layout.tsx (36:22) @ document

⨯ ReferenceError: document is not defined

at getCookie (./src/components/chat/chat-layout.tsx:26:24)

at useMountEffect (./src/components/chat/chat-layout.tsx:42:28)

at ChatLayout (./src/components/chat/chat-layout.tsx:78:5)

digest: "1286481958"

34 | function getCookie(name: string): string | undefined {

35 |

> 36 | const value = ; ${document.cookie};

| ^

37 | const parts = value.split; ${name}=);

38 | if (parts.length === 2) return parts.pop()?.split(";").shift();

39 | }

GET / 500 in 107ms

GET /.well-known/appspecific/com.chrome.devtools.json 404 in 64ms

 

이런 에러가 나옵니다...처음부터 token값이든 cookie 값이든 가져올 때 잘못 가져와서 그런건가요...? 제 생각에는 처음부터 가져올 때 잘못 작성한 게 있는 것 같아서 이 부분부터 해결해야 할 것 같습니다ㅠㅠ

여기저기 검색해보고 선생님께서 올려주신 소스코드도 보고 하는데 대체 어디가 문제인지 알 수가 없습니다..

 

그리고 한번 로그인 하면 그 뒤로 계속 자동으로 로그인 되는데, 이 부분도 어딜 수정해야 하는지 알려주실 수 있으실까요...?

 

항상 답변 주셔서 감사합니다ㅠㅠ

스승의 날인데 모쪼록 좋은 하루 보내세요!

Hong님의 프로필 이미지
Hong
지식공유자

한번 로그인을 진행을 하게 되면, 브라우저의 쿠키를 저장하게 됩니다.

 

개발자 도구에서 Application 이후 Cookie에서 값을 삭제하면 될 꺼 같습니다.

스크린샷 2025-05-15 오후 11.00.46.png
  • 현재 제 화면인데 해당 화면과 유사하게 접속하셔서 삭제하시면 됩니다.

     

Hong님의 프로필 이미지
Hong
지식공유자

우선 Login 컴포넌트에서

 

useEffect(() => {
    // Client-side cookie access to check if user is already authenticated
    const authCookie = document.cookie
      .split("; ")
      .find((row) => row.startsWith("auth="));
    if (authCookie) {
      router.push("/");
    }
  }, [router]);

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault();
    // Add login logic here

    const result = await api.post("/api/v1/auth/login", {
      name: username,
      password: password,
    });

    if (!result.data.token) {
      alert("존재하지 않은 User 입니다.");
      return;
    }

    document.cookie = `auth=${result.data.token}; path=/`;
    router.push("/");
  };

 

해당 소스에 들어오는 result.data.token 에 console.log를 찍어서 값을 확인해 봐야 할 꺼 같습니다.

cloverj0님의 프로필 이미지
cloverj0
질문자

안녕하세요! console.log에 찍어봤는데,

const handleSubmit = async (event: FormEvent) => 

이 안에서 찍히지 않는 것을 확인했습니다!! 혹시 따로 다운로드하거나 import 시켜야 할 것이 있는 건가요?

Hong님의 프로필 이미지
Hong
지식공유자

import는 아니고, 추가하신 로그가 정상적인 JWT 포멧인지 jwt.io에 접속해 확인을 해보셔야 할 꺼 같습니다.

Hong님의 프로필 이미지
Hong
지식공유자

에러 문구 자체가 일단 JWT의 일반적인 형태가 아니라는 에러가 발생하고 있어서요

cloverj0님의 프로필 이미지
cloverj0
질문자

안녕하세요! 답이 늦어져서 죄송합니다.

token값을 제가 "token"으로 넣는 바람에 그대로 "token"으로 들어가서 해당 에러가 나온 것 같습니다ㅠㅠ(그래서 해결되었습니다ㅎ)

정말..친절히 답 주셔서 감사합니다!!

0

안녕하세요, 인프런 AI 인턴입니다. cloverj0님.

JWTDecodeException 에러는 보통 JWT 토큰의 형식이 올바르지 않을 때 발생합니다. JWT 토큰은 일반적으로 header.payload.signature 형태로 이루어져 있어야 합니다. 에러 메시지에 따르면, 토큰이 예상하는 3개의 파트를 포함하고 있지 않음을 의미합니다. 이 문제는 다양한 원인으로 발생할 수 있으며, 다음과 같은 부분을 확인해 보세요.

1. 토큰 형식 확인

  • 먼저, 서버 쪽에서 실제 저장된 JWT 토큰의 형식이 올바른지 확인해보세요. 가끔 잘못된 값이 저장되거나 파싱될 때 문제가 생길 수 있습니다.

2. 토큰 발급 부분 확인

  • 토큰을 처음 생성하는 부분에서 올바르게 생성되었는지 재확인하세요. 토큰 생성시 header, payload, signature를 올바르게 설정되었는지 점검해 주세요.

3. Authorization 헤더 값

  • UserControllerV1Authorization 헤더에서 JWT 토큰을 올바르게 추출하고 있는지 확인하세요. JWT는 Bearer 접두사 없이 순수한 토큰 문자열이어야 합니다.

4. 디버깅 로그 추가

  • searchUser 메서드 실행 전후로 디버깅 로그를 추가하여 토큰 값이 어떻게 처리되고 있는지 확인해 보세요. 이렇게 하면 문제가 발생하는 시점을 더 자세히 파악할 수 있습니다.

JWT 관련한 문제를 해결하는데 도움이 될 수 있는 다음 자료도 참고해 보세요:
- JWT 토큰 형식과 구조 이해하기
- Spring Security와 JWT 통합 시 발생할 수 있는 일반적인 에러 해결

위의 내용을 참고하여 문제를 해결하시길 바랍니다. 제가 제공한 링크들은 유사한 문제 해결에 도움이 될 수 있으며, 추가적으로 궁금하신 점이 있으면 언제든지 질문해 주세요. 곧 지식공유자께서도 도움을 주실 것입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏

추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

cloverj0님의 프로필 이미지
cloverj0

작성한 질문수

질문하기