오래 못 할 짓 하지 않기

[ Spring boot Security ] 8. JWT 검증 필터 본문

혼자하기/연습 1) OAuth

[ Spring boot Security ] 8. JWT 검증 필터

쫑알bot 2024. 3. 3. 00:20
728x90

 

 

JWTFilter를 만든다. 그 클래스는 OncePerRequestFilter를 상속받는다.

 

 

 

로직은 간단하다. 

 

1. Authorization라는 이름의 쿠키에 담겨있는 값을 가져온다.


2. 그 값이 null이면 다음 필터로 넘기고 종료, 아니면 그 뒤 인증 단계를 거친다.


3. 그 토큰이 소멸되었는지 판단하고 그렇지 소멸되었다면 다음 필터로 넘기고 종료, 아니면 그 뒤 인증 단계를 거친다.

 

 

 

결과적으로 Null이 아니고 만료되지 않은 토큰만 필터를 통과한다.

 

코드▼

더보기
package com.example.oauthtest.jwt;

import com.example.oauthtest.dto.CustomOAuth2User;
import com.example.oauthtest.dto.UserDTO;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

public class JWTFilter  extends OncePerRequestFilter {

    private final JWTUtil jwtUtil;

    public JWTFilter(JWTUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }


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

        //cookie들을 불러온 뒤 Authorization Key에 담긴 쿠키를 찾음
        //로직 1) Authorization라는 이름의 쿠키에 담겨있는 값을 가져온다.
        //    2) 그 값이 null이면 다음 필터로 넘기고 종료, 아니면 그 뒤 인증 단계를 거친다.
        //    3) 그 토큰이 소멸되었는지 판단하고 그렇지 소멸되었다면 다음 필터로 넘기고 종료, 아니면 그 뒤 인증 단계를 거친다.


        String authorization = null;
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {

            if (cookie.getName().equals("Authorization")) {

                authorization = cookie.getValue();
            }


            //Authorization 헤더 검증
            if (authorization == null) {

                System.out.println("token null");
                filterChain.doFilter(request, response);

                //조건이 해당되면 메소드 종료 (필수)
                return;
            }

            //토큰
            String token = authorization;

            //토큰 소멸 시간 검증
            if (jwtUtil.isExpired(token)) {

                System.out.println("token expired");
                filterChain.doFilter(request, response);

                //조건이 해당되면 메소드 종료 (필수)
                return;
            }

            //여기까지 넘어왔다는 건, 토큰에 값이 있고 그 토큰이 만료되지 않았다는 것이다.
            // = 유효하다.

            //토큰에서 username과 role 획득
            String username = jwtUtil.getUsername(token);
            String role = jwtUtil.getRole(token);

            //userDTO를 생성하여 값 set
            UserDTO userDTO = new UserDTO();
            userDTO.setUsername(username);
            userDTO.setRole(role);

            //UserDetails에 회원 정보 객체 담기
            CustomOAuth2User customOAuth2User = new CustomOAuth2User(userDTO);

            //스프링 시큐리티 인증 토큰 생성
            Authentication authToken = new UsernamePasswordAuthenticationToken(customOAuth2User, null, customOAuth2User.getAuthorities());

            //세션에 사용자 등록
            SecurityContextHolder.getContext().setAuthentication(authToken);

            filterChain.doFilter(request, response);

        }

    }


}

 

 

그리고 이 필터가 Config에서 실행될 수 있도록 넣어준다.

 

 

코드▼

더보기
     //JWTFilter 추가
        http
                .addFilterBefore(new JWTFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class);