IT Developer/Spring

Spring 기초 <17. Spring Boot에서 JWT(Json Web Token) 인증 구현>

TEMA_ 2025. 4. 3. 13:01
반응형

스프링 Spring

17. Spring Boot에서 JWT(Json Web Token) 인증 구현

 

안녕하세요! 태마입니다.

Spring 기초 강좌입니다.

 

강좌의 경우 

1. 주제 간단 정리

2. 상세 주제 정리

으로 이루어져 있습니다.

 

스프링 Spring

포스팅 시작하겠습니다 :)

 


 

1. 주제 간단 정리

 

1. JWT(Json Web Token)란?

JWT(Json Web Token)는 사용자 인증 정보를 포함한 토큰을 발급하여 인증을 수행하는 방식
무상태(Stateless) 인증 방식으로, 세션을 저장할 필요 없이 토큰을 통해 사용자 인증을 유지 가능

📌 JWT의 주요 특징

특징설명
무상태(Stateless) 서버에서 세션을 관리할 필요 없음
Base64 인코딩된 JSON JSON 형식의 데이터가 Base64로 인코딩되어 전달됨
디지털 서명(Signature) 포함 토큰의 무결성을 검증하기 위해 서명 포함
토큰 기반 인증 HTTP 헤더에 포함하여 API 요청마다 인증 수행

📌 JWT는 "REST API와 함께 사용할 때 효율적인 인증 방식"


2. Spring Boot에서 JWT 인증이 필요한 이유

세션 기반 인증(Session-based Authentication)은 서버에서 세션을 저장해야 하므로 확장성이 떨어짐
JWT는 서버에서 세션을 유지할 필요 없이 토큰을 활용하여 인증을 유지 가능

📌 JWT 인증 방식이 필요한 경우
RESTful API를 제공하는 경우 (무상태 인증이 필요할 때)
여러 서비스(API Gateway, Microservices)에서 인증을 공유해야 할 때
클라이언트가 인증 상태를 유지하면서 API 요청을 할 때

📌 JWT를 사용하면 "무상태 인증을 제공하여 확장성이 뛰어나며, REST API에 적합"


✅ 여기까지 JWT의 개념과 필요성을 배웠습니다!
👉 "그렇다면, Spring Boot에서 JWT를 어떻게 구현할까?"
✅ 2부에서 Spring Boot에서 JWT 생성, 검증, 필터 적용 방법을 배워봅시다!

 

반응형

 

2. 상세 주제 정리

 

1. JWT 의존성 추가

Spring Boot에서 JWT를 사용하려면 jjwt 라이브러리를 추가해야 함

📌 1️⃣ build.gradle 설정

dependencies {
    implementation 'io.jsonwebtoken:jjwt:0.11.5'
}

JWT 토큰을 생성하고 검증하기 위한 라이브러리 추가


2. JWT 토큰 생성 및 검증 클래스 구현

JWT를 생성하고 검증하는 JwtTokenProvider 클래스를 작성

📌 JwtTokenProvider 클래스

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;

public class JwtTokenProvider {

    private static final String SECRET_KEY = "your-secret-key-your-secret-key"; // 256-bit key 필요
    private static final long EXPIRATION_TIME = 86400000; // 1일 (24시간)

    private static final Key key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());

    // JWT 생성
    public static String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(key, SignatureAlgorithm.HS256)
                .compact();
    }

    // JWT 검증
    public static boolean validateToken(String token) {
        try {
            Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
            return true;
        } catch (JwtException e) {
            return false;
        }
    }

    // JWT에서 사용자 이름 추출
    public static String getUsernameFromToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }
}

JWT를 생성, 검증, 사용자 정보를 추출하는 기능을 구현

📌 JWT를 사용하면 "서버에서 세션을 유지하지 않아도 인증을 관리 가능"


3. JWT 필터 구현 및 Security 설정 적용

JWT 인증을 필터로 적용하여, API 요청마다 JWT를 검증하도록 설정

📌 JwtAuthenticationFilter 클래스

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 
            throws ServletException, IOException {
        String token = request.getHeader("Authorization");

        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
            if (JwtTokenProvider.validateToken(token)) {
                String username = JwtTokenProvider.getUsernameFromToken(token);
                // Spring Security Context에 저장하는 과정 (생략 가능)
            }
        }

        filterChain.doFilter(request, response);
    }
}

클라이언트 요청에서 JWT를 검증하고, 유효하면 요청을 계속 처리

📌 JWT 인증 필터를 추가하면 "모든 요청에서 JWT 검증을 수행 가능"


📌 SecurityConfig 클래스 – JWT 필터 적용

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable()) // JWT는 CSRF 보호가 필요 없음
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/login").permitAll()
                .anyRequest().authenticated()
            )
            .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

JWT 필터를 Security 설정에 추가하여 인증을 수행하도록 설정

📌 JWT 필터를 적용하면 "세션 없이도 인증 상태를 유지할 수 있음"


4. 로그인 시 JWT 발급 API 구현

사용자가 로그인하면 JWT를 발급하여 클라이언트에 전달

📌 AuthController – 로그인 시 JWT 발급

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
public class AuthController {

    @PostMapping("/login")
    public ResponseEntity<String> login(@RequestParam String username, @RequestParam String password) {
        // 여기서는 단순 예제, 실제로는 DB에서 사용자 검증 필요
        if ("user".equals(username) && "password".equals(password)) {
            String token = JwtTokenProvider.generateToken(username);
            return ResponseEntity.ok(token);
        }
        return ResponseEntity.status(401).body("Invalid credentials");
    }
}

로그인 성공 시 JWT를 발급하여 클라이언트에 반환

📌 클라이언트는 "JWT를 받아서 이후 요청마다 인증에 사용 가능"


✅ 여기까지 Spring Boot에서 JWT 인증을 구현하는 방법을 배웠습니다!
👉 "그렇다면, OAuth2.0 인증 및 소셜 로그인(Google, Facebook, GitHub) 적용은 어떻게 할까?"
✅ 다음 회차에서 OAuth2.0 인증 및 소셜 로그인(Google, Facebook, GitHub) 적용을 배워봅시다!

 

 

반응형