TIL 45 [ Spring 심화 프로젝트 ( Day 4 ) - 구현 ( JWT 로그인 필터 기능 ), PR 리뷰/병합 ]

2025. 4. 25. 23:27·[내일배움캠프-Sparta]/Spring 6기
반응형

어제 말했듯이 , 오전에 접속을하고 40분뒤에  병원을 갔다.  

✅ PR ( Pull Request ) 

오늘부터 각 기능별로 병합을 PR ( pull request ) 을 보내서 병합을 진행하였다.

 👀🔥 병원 가기전에 내 기능을 PR을 보내서 병원 진료를 받으러 갔다. 눈이 너무 안좋아서 요즘 따라 전자기기 보기가 힘들다.. 눈 관리를 잘해야겠다..

 

병원 갔다오고 4시경이 되었는데 하루의 절반이 삭제가 되버렸다...

 

그러고 오자마자 PR 코드리뷰를 진행하였다. 처음으로 PR 코드리뷰를 제대로 하다보니 알게 된게 많았다. 실무에서도 코드리뷰를 이런식으로 진행을 하는 것을 느꼈고, Megre Request는 절대로 누르지말고 모든 것이 다 해결이 되면 누르는 식으로 가야한다.

⭐ 처음 알았던게 PR을 진행할때 PR Request가 열려있을때 해당 브랜치에서 또 푸쉬가 된다면, 자동으로 푸쉬된 내용들이 pr에 담겨져서 들어온다. 

✅ 로그인 필터 

Spring Security 없이 JWT기반으로 인증/인가를 진행하였다. 

JwtProvider

jwt을 생성하고 검증하는 역할, 토큰 검증 유효시간과 secretKey는 properties에 직접 선언하여서 인코딩한 값을 주었다.

그리고 @Value 어노테이션을 활용해 값을 jwt.secret.key로 담아서 추가해주었다.

/**
 *  JWT(Token)을 생성하고 검증하는 역할인 클래스
 */
@Component
@Slf4j
public class JwtProvider {

    @Value("${jwt.secret.key}")
    private String secretKey; // 토큰을 만들 때 이 값을 사용한다.
    private Key key;
    private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
    private final long EXPIRATION_TIME = 1000 * 60 * 60; // 토큰 유효시간 : 1시간

    @PostConstruct
    public void init() {
        // 인코딩 값을 디코딩함
        byte[] bytes = Base64.getDecoder().decode(secretKey);
        // 바이트 배열을 받아서
        this.key = Keys.hmacShaKeyFor(bytes);

    }

    public String createToken(Long userId) {
        return Jwts.builder()
                .setSubject(String.valueOf(userId))
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(key, signatureAlgorithm) // 시크릿키와 암호화 알고리즘을 넣어준다. ( 서명 = 싸인 )
                .compact();
    }

    public Long getUserIdFromToken(String token) {
        String subject = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody()
                .getSubject();

        return Long.parseLong(subject);
    }

    public Boolean validateToken(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(key)
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (UnsupportedJwtException e) {
            log.error(e.getMessage());
        } catch (MalformedJwtException e) {
            log.error(e.getMessage());
        } catch (SignatureException e) {
            log.error(e.getMessage());
        } catch (ExpiredJwtException e) {
            log.error(e.getMessage());
        } catch (IllegalArgumentException e) {
            log.error(e.getMessage());
        }

        return false;
    }
}

JwtAuthFilter

필터는 세션과 동일하게, jwt기반으로도 거의 방법은 동일하다.

로그인 필터를 걸어줌으로써, 화이트 리스트에 없는것 들은 Jwt 기반으로 인증을 무조건 받아야 한다. 그러고 jwt 기반으로 하기 때문에 JwtProvider로 의존성 주입을 받고, doFilter로 오버라이딩하여서 요청, 응답 값을 받는다. 

매개변수인 servletRequest와 servletResponse는 각각 (HttpServletRequest) 와 (HttpServletResponse) 로 다운캐스팅 함.

filterChain.dofilter(request, response)로 다음 필터가 있으면 그 요청,응답으로 보내주는 역할을 한다.

public class JwtAuthFilter implements Filter {

    private final JwtProvider jwtProvider;
    private final List<String> WHITE_LIST = List.of("/", "/authors/login", "/users/signup");

    public JwtAuthFilter(JwtProvider jwtProvider) {
        this.jwtProvider = jwtProvider;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 0. WHITE_LIST에 포함된 경로 검증 없이 통과
        if(isWhiteListed(request)) {

            filterChain.doFilter(request, response);
            return;
        }

        // 1. 토큰을 가져온다
        String token = extractedTokenFromHeader(request);
        // 2. 토큰을 검증
        if(token != null && jwtProvider.validateToken(token)) {
            // 3. 토큰에서 사용자 정보를 가져온다.
            Long userIdFromToken = jwtProvider.getUserIdFromToken(token);
            request.setAttribute("userId",userIdFromToken);
            filterChain.doFilter(request, response);
        } else {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("토큰 오류 발생"); 
        }
    }

    //  와일드 카드가 포함된 문자열 패턴과 요청 URI가 일치 하는지 확인
    private boolean isWhiteListed(HttpServletRequest request) {
        return WHITE_LIST.stream().anyMatch(uriPattern -> PatternMatchUtils.simpleMatch(uriPattern, request.getRequestURI()));
    }

    private String extractedTokenFromHeader(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        // 예외처리 null 처리
        String token = bearerToken.substring(7);

        return token;
    }
}

주말에 공부와 다음주를 대비하기 위해서 프로젝트를 보완해야겠다.

🔥 새로 알게 된것

CTRL + ALT + M  = 메소드를 자동으로 만들어줌

CTRL + ALT + O =  사용하지않는 import 제거

반응형

'[내일배움캠프-Sparta] > Spring 6기' 카테고리의 다른 글

TIL 47 [ Spring 심화 프로젝트 ( D-day ) - 발표/마무리, 트러블 슈팅 ]  (0) 2025.04.29
TIL 46 [ Spring 심화 프로젝트 ( Day 5 ) - 마무리 작업 ( ppt, 대본, ERD/API 명세서 리뉴얼) ]  (0) 2025.04.28
TIL 44 [ Spring 심화 프로젝트 ( Day 3 ) - 구현 ( 회원탈퇴, JWT 로그인 기능 ) ]  (0) 2025.04.24
TIL 43 [ Spring 심화 프로젝트 ( Day2 ) - 구현 ( 회원 가입, 전체 유저 조회, 회원 정보 수정, 암호화 처리 ) ]  (0) 2025.04.23
TIL 42 - [ Spring 심화 프로젝트 ( Day 1 ) - 설계 ( 와이어프레임, ERD, API 명세서 ) ]  (0) 2025.04.22
'[내일배움캠프-Sparta]/Spring 6기' 카테고리의 다른 글
  • TIL 47 [ Spring 심화 프로젝트 ( D-day ) - 발표/마무리, 트러블 슈팅 ]
  • TIL 46 [ Spring 심화 프로젝트 ( Day 5 ) - 마무리 작업 ( ppt, 대본, ERD/API 명세서 리뉴얼) ]
  • TIL 44 [ Spring 심화 프로젝트 ( Day 3 ) - 구현 ( 회원탈퇴, JWT 로그인 기능 ) ]
  • TIL 43 [ Spring 심화 프로젝트 ( Day2 ) - 구현 ( 회원 가입, 전체 유저 조회, 회원 정보 수정, 암호화 처리 ) ]
dimenshun
dimenshun
한 소년의 개발 일기
    반응형
  • dimenshun
    Dev Life Notes
    dimenshun
  • 전체
    오늘
    어제
    • 분류 전체보기 (268)
      • CS (23)
        • 자료구조 (0)
        • 알고리즘 (0)
        • 컴퓨터 구조 (8)
        • 네트워크 (6)
        • 운영체제 (3)
        • DB ( + SQLD ) (5)
        • SW공학 (1)
      • 프로그래밍 (3)
        • Java (0)
        • Spring (0)
        • HTML,CSS (3)
        • JavaScript (0)
      • 개발 툴 (7)
        • Git(버전관리) (1)
        • Docker (3)
        • AWS (2)
        • JSP (1)
      • 코딩테스트(Algorithm) (125)
        • 백준 (6)
        • 프로그래머스 (119)
      • [내일배움캠프-Sparta] (110)
        • Spring 6기 (106)
        • KPT 회고 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    웹
    web
    docker
    KPT
    컴퓨터구조
    트랜잭션
    세션
    코딩테스트
    배포
    운영체제
    db
    메모리
    백엔드
    network
    알고리즘
    Python
    네트워크
    Til
    It
    OS
    cs
    Java
    AWS
    내일배움캠프
    Testcode
    SQL
    spring
    개발자
    CPU
    SQLD
  • hELLO· Designed By정상우.v4.10.3
dimenshun
TIL 45 [ Spring 심화 프로젝트 ( Day 4 ) - 구현 ( JWT 로그인 필터 기능 ), PR 리뷰/병합 ]
상단으로

티스토리툴바