2025년 10월 22일 수요일 (98일차)

Jeonghoon·2025년 10월 22일

jeonghoon's Study

목록 보기
101/128

🔑 JWT & 🛡️ Spring Security 정리


🧾 JWT (JSON Web Token)

💡 개념 요약

  • 정의: 웹에서 사용하는 자바스크립트 기반의 특정한 데이터를 대신하는 증표
  • 목적: 데이터를 직접 노출하지 않고 토큰(Token) 으로 대체하여 보안을 강화
  • 사용처: 사용자 인증, 정보 보호, 세션 대체 등
  • 알고리즘: 주로 SHA-256 기반의 HMAC 해시 알고리즘을 사용하여 비밀키 생성

🔍 핵심 개념

용어설명
토큰(Token)사용자의 인증정보를 담은 암호화된 문자열
비밀키(Secret Key)토큰 서명 및 검증에 사용되는 키 (32자 이상 권장)
Claim토큰에 포함되는 데이터 (예: 사용자 ID, 권한 등)
Header토큰의 타입과 서명 알고리즘 정보 포함
Payload사용자 데이터(Claim) 포함 영역
SignatureHeader + Payload를 비밀키로 서명한 값

⚙️ JWT 생성 / 검증 / 추출

1️⃣ 비밀키 생성

private final String secret = ""; // 32자 이상 비밀키
private final Key secretKey = Keys.hmacShaKeyFor(secret.getBytes());

2️⃣ 토큰 생성

String token = Jwts.builder()
    .claim(key, value)                         // 토큰에 데이터 추가
    .setIssuedAt(new Date())                   // 발급 시간
    .setExpiration(new Date(System.currentTimeMillis() + 1000 *)) // 만료 시간
    .signWith(secretKey, SignatureAlgorithm.HS256) // 서명 알고리즘
    .compact();                                // 토큰 생성 완료

3️⃣ 토큰 검증

Jwts.parser()
    .setSigningKey(secretKey)    // 서명 검증용 비밀키
    .build()
    .parseClaimsJws(token);      // 검증할 토큰 대입

4️⃣ 토큰 추출

Jwts.parser()
    .setSigningKey(secretKey)
    .build()
    .parseClaimsJws(token)
    .getBody();  // 검증 후 payload 추출

🍪 JWT + 쿠키 연동

  • 회원정보를 기반으로 JWT를 생성한 후 쿠키에 저장할 수 있다.
Cookie cookie = new Cookie("loginUser", jwtService.generateToken(uid, urole));
항목설명
쿠키 이름loginUser
쿠키 값JWT 문자열
사용 목적로그인 상태 유지 및 인증 정보 전달

🛡️ Spring Security

💬 개념 요약

  • Spring Security는 HTTP 요청에 대한 권한 제어 및 인증/인가를 담당한다.
  • SecurityConfig를 생성하여 요청 경로별 접근 권한을 커스텀할 수 있다.

⚙️ SecurityConfig 예시

@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
    // 1️⃣ 요청 경로별 권한 설정
    httpSecurity.authorizeHttpRequests(auth -> auth
        .requestMatchers("/api/user/info").hasAnyRole("USER", "ADMIN")
        .requestMatchers("/api/admin/**").hasRole("ADMIN")
        .requestMatchers("/**").permitAll()
    );

    // 2️⃣ CSRF 비활성화 (개발 단계 권장)
    httpSecurity.csrf(csrf -> csrf.disable());

    // 3️⃣ 세션 비활성화 (STATELESS → JWT 기반 인증)
    httpSecurity.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

    // 4️⃣ JWT 필터 등록 (UsernamePasswordAuthenticationFilter 전에 실행)
    httpSecurity.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

    return httpSecurity.build();
}

🔐 주요 설정 요약

설정 항목코드설명
권한 설정.requestMatchers("/api/admin/**").hasRole("ADMIN")특정 경로에 대한 권한 제한
모든 권한 허용.requestMatchers("/**").permitAll()권한 없는 요청 허용
CSRF 비활성화httpSecurity.csrf(csrf -> csrf.disable())POST/PUT 요청 허용
세션 끄기sessionCreationPolicy(SessionCreationPolicy.STATELESS)세션 대신 JWT 사용
JWT 필터 추가.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)사용자 정의 토큰 필터 등록

🔄 Spring Security + JWT 연동

🔧 필터 내부 동작 (쿠키 기반 인증)

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

    // 1️⃣ 쿠키에서 JWT 추출
    String token = null;
    if (request.getCookies() != null) {
        for (Cookie cookie : request.getCookies()) {
            if (cookie.getName().equals("loginUser")) {
                token = cookie.getValue();
            }
        }
    }

    // 2️⃣ JWT 유효성 검증 및 사용자 정보 추출
    if (token != null && jwtService.validateToken2(token)) {
        String uid = jwtService.getUid(token);
        String urole = jwtService.getUrole(token);

        // 3️⃣ Spring Security 인증 객체 생성
        UsernamePasswordAuthenticationToken newAuthenticationToken =
            new UsernamePasswordAuthenticationToken(uid, null, 
                List.of(new SimpleGrantedAuthority("ROLE_" + urole)));

        // 4️⃣ SecurityContext에 인증 정보 저장
        SecurityContextHolder.getContext().setAuthentication(newAuthenticationToken);
    }

    // 5️⃣ 다음 필터로 전달
    filterChain.doFilter(request, response);
}

⚙️ 작동 순서 요약

단계설명
1️⃣쿠키에서 "loginUser" 토큰 추출
2️⃣jwtService.validateToken2()로 유효성 검증
3️⃣토큰에서 uid, urole 추출
4️⃣UsernamePasswordAuthenticationToken 생성 후 SecurityContext에 등록
5️⃣나머지 필터 체인 실행

0개의 댓글