스프링부트 jwt

Yeeun·2025년 5월 22일
0

SpringBoot

목록 보기
40/46
post-thumbnail

MemberInitialize 파일이 test폴더 안에 있는거라 일반자바 실행하듯이 ctrl+F11 눌러서 실행
h2 켜져있어야함
엔티티매니저 어쩌고 오류 뜨는건 어플리케이션 프로퍼티 설정이 잘못된 경우가 많음
확인해보니 유알엘을 잘못입력해둠

jwt

쿠키는 저장방식, jwt는 토큰

jwt는 서버에서 토큰을만들어서 줬으니 내가 만든거니까 신뢰한다 하면서 얘가 가져온 유저아이디랑 그런걸 신뢰하고 접속시도를 시켜주는거고 , 쿠키 세션아이디는 처음엔 디비랑 대조하고 세션아이디를 가지게되면 서버에서 그걸 30분간 기억하고있으니 접속허용

✅ JWT 흐름 정리

Stateless 인증 (상태를 서버에 안 저장)

  1. 클라이언트가 로그인 요청 (ID, PW 전송)
  2. 서버는 DB에서 사용자 정보 대조 후 인증 성공
  3. 서버는 JWT 토큰 생성해서 클라이언트에 응답
  4. 클라이언트는 JWT를 Authorization: Bearer ~ 헤더로 들고 다님
  5. 서버는 이 JWT의 서명만 확인하고, 토큰에 담긴 유저 정보를 신뢰함
    → 별도로 DB 조회 X (필요하면 하기도 함. 예: 탈퇴 여부 확인 등)

✅ 세션/쿠키 흐름 정리

Stateful 인증 (서버가 상태 기억)

  1. 클라이언트가 로그인 요청 (ID, PW 전송)
  2. 서버는 DB에서 사용자 정보 대조 후 인증 성공
  3. 서버는 세션 저장소(메모리, Redis 등)에 사용자 정보를 저장하고,
    세션 ID를 생성해서 클라이언트에게 쿠키에 담아 보냄
  4. 클라이언트는 그 이후 요청마다 이 세션 ID 쿠키를 자동 전송
  5. 서버는 그 세션 ID를 보고 세션 저장소에서 사용자 정보 꺼내서 인증 처리

👉 네, 맞아요. 세션도 처음엔 DB 조회해서 로그인 인증한 다음 세션을 만드는 거예요.


✅ 핵심 차이 한 줄 요약

구분JWT쿠키+세션
상태 저장❌ 서버가 기억 안 함✅ 서버가 기억함
DB 조회로그인 시 한 번만 (보통)로그인 시 한 번 + 이후는 세션 기반
인증 처리토큰 서명만 확인세션 ID 보고 사용자 정보 꺼냄
로그아웃 처리어려움 (블랙리스트 필요)세션 삭제로 간단

토큰덕에 필터는 다 통과했는데, 세션이없는상황이니 서버는 응답하고나서 디비에 불러온 데이터를 삭제했으니 로그인 안한유저라 판단하니 , 마지막 인가필터 앞에 얘가 로그인한 애라는걸 처리하는 작업이 필요.


네, 아주 중요한 포인트를 잘 짚었어요. 지금 말한 건 JWT 기반 인증 흐름에서 흔히 발생하는 오해 중 하나인데, 그걸 정확히 짚으셨어요. 정리해드릴게요.


🧩 JWT에서는 세션이 없으니…

  • JWT 인증을 하면 UsernamePasswordAuthenticationFilter에서 토큰을 받아 인증하고
  • 그 후 SecurityContext에 인증 정보를 넣어줘야
  • 이후 인가 과정(AuthorizationFilter, Controller 등)에서 "로그인한 사용자"로 인식됩니다.

✅ 핵심 개념: SecurityContext에 Authentication 저장이 필요

JWT를 검증했다고 해서 자동으로 "로그인한 사용자"로 인식되는 게 아니에요.
명시적으로 SecurityContextHolderAuthentication 객체를 넣어줘야 합니다.


🎯 그래서 필요한 작업은?

🔐 인증 성공 후 필터에서 하는 일 (예시: JWTAuthorizationFilter)

Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);

이걸 해줘야 인가 필터들이 isAuthenticated()hasRole() 같은 조건을 만족할 수 있어요.


🔄 왜 디비에서 정보를 못 가져오는가?

만약 이걸 안 해주면, 서버는 사용자가 인증됐다는 컨텍스트 정보가 없기 때문에,
Controller나 이후 인가 필터에서 "로그인하지 않은 사용자"로 판단합니다.
JWT를 헤더로 들고 와도, "누군지 모르는 놈이니까" 정보 제공 안 해주는 거죠.


✅ 정리하면

순서설명
1JWT를 헤더에서 꺼내고
2서명 검증 + 유효시간 검증
3토큰에 담긴 username 등으로 UserDetails 불러오기
4Authentication 객체 생성
5SecurityContextHolder.getContext().setAuthentication(...)로 저장 ← 이게 중요
6이후 필터나 컨트롤러에서 "로그인한 사용자"로 인식됨

🔧 예: JWTAuthorizationFilter 내부 코드 일부

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

    String header = request.getHeader("Authorization");
    if (header == null || !header.startsWith("Bearer ")) {
        chain.doFilter(request, response);
        return;
    }

    String token = header.replace("Bearer ", "");
    String username = JWT.require(Algorithm.HMAC256(secretKey))
                        .build()
                        .verify(token)
                        .getClaim("username")
                        .asString();

    if (username != null) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(auth);
    }

    chain.doFilter(request, response);
}

필터는 통과했지만 SecurityContext에 아무 정보도 안 들어가 있으면,
세션이 없기 때문에 "로그인한 사용자" 상태로 인식되지 않습니다.

이게 JWT 인증의 핵심 함정 포인트예요.


인가 필터 생성 확인

매니저 jwt 복사해서 헤더에 넣고 겟으로 호출
매니저로그인성공, 매니저권한 인가 성공

0개의 댓글