[JWT] JwtFilter 사용하기

nasohi·2026년 4월 11일

JWT

목록 보기
5/5

JWT 로그인 흐름에서 로그인은 LoginFilter가 처리했다.
그렇다면 로그인 이후 요청은 어떻게 인증될까?

이 역할을 담당하는 것이 바로 JwtFilter 이다.

JWTFilter

JwtFilter란?
JwtFilter : 요청에 포함된 JWT를 검증하여 인증 상태를 만들어주는 필터

왜 JwtFilter가 필요한가?
JWT 방식은 서버가 로그인 상태를 저장하지 않는다. (Stateless)
따라서 요청이 올 때마다 이 사용자가 로그인한 상태인지 다시 확인해야 한다.

전체 동작 흐름

클라이언트 요청 (JWT 포함)
→ JwtFilter 실행
→ 토큰 검증
→ 사용자 정보 추출
→ SecurityContext에 저장
→ 컨트롤러 실행 (로그인된 상태로 인식)

코드 분석

전체 코드

@RequiredArgsConstructor
public class JwtFilter extends OncePerRequestFilter {

    private static final String BEARER_PREFIX = "Bearer ";
    private final JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        String token = resolveToken(request);

        if (token == null) {
            filterChain.doFilter(request, response);
            return;
        }

        if (jwtUtil.isExpired(token)) {
            filterChain.doFilter(request, response);
            return;
        }
        setAuthentication(token);
        filterChain.doFilter(request, response);
    }
    
    private String resolveToken(HttpServletRequest request) {

        String header = request.getHeader("Authorization");

        if (header == null || !header.startsWith(BEARER_PREFIX)) {
            return null;
        }

        return header.substring(BEARER_PREFIX.length());
    }

    private void setAuthentication(String token) {

        String username = jwtUtil.getUsername(token);
        String role = jwtUtil.getRole(token);

        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(username);
        userEntity.setPassword("temp");
        userEntity.setRole(role);

        CustomUserDetails userDetails = new CustomUserDetails(userEntity);

        UsernamePasswordAuthenticationToken authToken =
                new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );

        SecurityContextHolder.getContext().setAuthentication(authToken);
    }
}

doFilterInternal() : 요청이 들어올 때마다 실행되는 메서드

 // 요청 올때마다 실행되는 메서드
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        // 토큰 꺼냄
        String token = resolveToken(request);

        // 토큰 없으면 그냥 통과
        if (token == null) {
            filterChain.doFilter(request, response);
            return;
        }

        // 토큰 만료 체크
        if (jwtUtil.isExpired(token)) {
            // 다음 필터로 넘김
            filterChain.doFilter(request, response);
            return;
        }
        // 인증 세팅
        setAuthentication(token);
        filterChain.doFilter(request, response);
    }
  • 모든 요청에 대해 JWT를 검사하고
  • 인증을 만들지 말지 결정하는 제어 메서드
  • 동작 흐름

    	1.	resolveToken()을 통해 요청 헤더에서 JWT를 꺼낸다
    	2.	토큰이 없으면 → 로그인하지 않은 사용자이므로 그냥 통과
    	3.	토큰이 만료되었으면 → 인증하지 않고 통과
    	4.	토큰이 유효하면 → setAuthentication()을 호출하여 인증 생성
    	5.	이후 요청을 다음 필터로 전달한다

이 메서드는 인증을 할지 말지 판단하는 역할이다. JWT가 없거나 문제가 있으면 건드리지 않고 넘기고, 정상적인 경우에만 인증을 만든다.

resolveToken() : 요청 헤더에서 JWT를 꺼내는 메서드

  private String resolveToken(HttpServletRequest request) {

        String header = request.getHeader("Authorization");

        // 토큰 없으면 로그인 안한 사용자이므로 그냥 통과
        if (header == null || !header.startsWith(BEARER_PREFIX)) {
            return null;
        }

        // "Bearer" 제거하고 토큰만 추출
        return header.substring(BEARER_PREFIX.length());
    }
  • HTTP 요청 헤더에서 JWT를 꺼내는 역할
  • Authorization: Bearer 형식에서 토큰만 추출
  • 동작 흐름

    	1.	Authorization 헤더 값을 가져온다
    	2.	헤더가 없거나 Bearer 로 시작하지 않으면 → JWT 없음 → null 반환
    	3.	Bearer  문자열을 제거하고 실제 JWT 문자열만 반환

JWT는 항상 "Bearer token " 형태로 전달되므로 순수 토큰만 꺼내야 한다.

setAuthentication()

   //SecurityContext에 인증 정보 저장
    private void setAuthentication(String token) {

        // 토큰에서 정보 꺼냄 (JWT에 있던 값)
        String username = jwtUtil.getUsername(token);
        String role = jwtUtil.getRole(token);

        // User 객체 생성
        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(username);
        userEntity.setPassword("temp");
        userEntity.setRole(role);

        // UserDetails 생성 (Spring Security는 UserDetails만 이해하므로)
        CustomUserDetails userDetails = new CustomUserDetails(userEntity);

        // 인증 객체 생성
        UsernamePasswordAuthenticationToken authToken =
                new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );

        // SecurityContext에 저장 -> 로그인된 상태로 인식
        SecurityContextHolder.getContext().setAuthentication(authToken);
    }
  • JWT에 들어있는 정보를 기반으로 Spring Security의 인증 객체(Authentication)를 생성하는 메서드

  • 동작 흐름

    	1.	JWT에서 username, role 정보 추출
    	2.	해당 정보로 User 객체 생성 (DB 조회 없이 JWT 기반으로 생성)
    	3.	Spring Security가 사용하는 UserDetails 객체로 변환
    	4.	UsernamePasswordAuthenticationToken을 생성하여 인증 객체 구성
    	5.	SecurityContext에 저장

즉 JWT -> Authentication 객체 생성 -> SecurityContext 저장의 과정이다.

0개의 댓글