본문 바로가기
Java/Spring with Error

[해결방법] JWT Login 시, accessToken이 null

by HJ0216 2024. 8. 18.

JWT Login 시, accessToken이 null

Environment
Language: Java
DB: MySQL

 

오류

private Claims parseClaims(ServletRequest request) {
    String accessToken = SecurityUtils.resolveToken((HttpServletRequest) request);
    if(accessToken == null)
        return null;

    Key secretKey = Keys.hmacShaKeyFor(JWT_SECRET.getBytes(StandardCharsets.UTF_8));

    return Jwts.parserBuilder()
            .setSigningKey(secretKey)
            .build()
            .parseClaimsJws(accessToken)
            .getBody();
}

Header Type, Request Body의 데이터가 정확함에도 accessToken이 null

 

 

원인

@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws IOException, ServletException {
    // 1. Request Header에서 JWT 토큰 추출
    Authentication authentication = jwtTokenProvider.getAuthentication(request);

    // 2. 토큰 유효성 검사
    // 토큰이 유효할 경우, 토큰에서 Authentication 객체를 가지고 와서 SecurityContext에 저장
    if (authentication != null && jwtTokenProvider.isValidToken(request)) {
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    filterChain.doFilter(request, response);
    // 현재 필터가 요청을 처리한 후, 필터 체인의 다음 필터로 요청과 응답을 전달
}

 

SpringSecurity와 JWT가 동작하는 과정

  1. 애플리케이션 시작 → Spring Security의 초기화 및 설정 과정(Filter 등)
  2. API 호출 → JwtAuthenticationFilter 요청 처리
    필터 통과: 요청을 다음 필터로 전달
    필터 통과 X: 오류 반환
  3. 필터 체인을 모두 통과한 요청은 Controller로 전달
  4. Controller → UserService 호출
  5. UserService에서 AuthenticationManager은 UserDetailsService 호출
  6. AuthenticationManagerBuilder 동작
  7. AuthenticationManagerBuilder에서 사용자가 제공한 정보(이메일과 비밀번호)를 확인
    * 사용자가 입력한 이메일과 비밀번호를 담은 인증 토큰 생성
  8. AuthenticationManagerBuilder에서 authentificate() 호출하여 인증 시도
    내부적으로 CustomUserDetailsService의 loadUserByUsername() 호출
    *주어진 이메일로 데이터베이스에서 사용자를 찾아서 그 정보를 UserDetails 객체로 반환
  9. AuthenticationManagerBuilder에서 6과 7의 객체 비교
    * 인증 성공: Authentication 객체는 SecurityContext에 저장, 이후의 요청에서 사용자 정보를 참조할 수 있음
    * 인증 실패: BadCredentialsException 발생
  10. UserService에서 JwtTokenProvider의 generateToken() 호출
 
JwtAuthenticationFilter 처리 시, 모든 요청에 대해 getAuthentification() 동작

→ 로그인 시에는 token이 없어 Header에 token을 넣고 요청할 수 없음

→ accessToken이 null

 

⭐ Controller 처리 전에 오류가 발생, Controller에서 디버그해도 넘어오지 않음⭐

 
 

해결

@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws IOException, ServletException {
    String accessToken = SecurityUtils.resolveToken(request);

    if (accessToken != null && jwtTokenProvider.isValidToken(request)) {
        Authentication authentication = jwtTokenProvider.getAuthentication(request);
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    filterChain.doFilter(request, response);
}

getAuthentification()이 아닌 토큰을 추출하는 메서드(resolveToken())를 수행

→ null이 아닐 때 getAuthentification() 수행