Springboot

🚀 Springboot 리프레시 토큰(Refresh Token) 적용 방법

수아파파's 2025. 2. 13. 21:36
반응형

서론 - JWT 인증 방식과 리프레시 토큰이 필요한 이유
본론 - 스프링부트에서 리프레시 토큰 적용 방법 (구현 코드 포함)
결론 - 리프레시 토큰을 활용한 인증 시스템의 장점과 확장 가능성


1️⃣ 서론: JWT 인증 방식과 리프레시 토큰이 필요한 이유

🔹 JWT 기반 인증 방식의 문제점

  • **Access Token(엑세스 토큰)**은 만료 기한이 있어 일정 시간이 지나면 다시 로그인해야 함
  • 보안 강화를 위해 토큰 만료 시간을 짧게 설정하면, 사용자가 불편해짐
  • 한 번 발급된 JWT는 변경 불가능(Stateless), 만료되면 새로 로그인해야 함

🔹 리프레시 토큰(Refresh Token)이란?

  • Access Token이 만료되었을 때 새로운 토큰을 발급받기 위해 사용하는 토큰
  • 보통 Access Token보다 긴 유효기간을 가짐
  • Refresh Token이 유효하면, 사용자는 다시 로그인할 필요 없이 자동으로 Access Token을 갱신 가능

즉, 리프레시 토큰을 사용하면 보안성을 유지하면서도 사용자 경험을 개선할 수 있음!


2️⃣ 본론: 스프링부트에서 리프레시 토큰 적용 방법

🔹 1. JWT 관련 의존성 추가

📌 Spring Boot 프로젝트의 pom.xml에 JWT 관련 라이브러리를 추가.

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.11.5</version>
</dependency>

🔹 2. JWT 토큰 생성 & 검증을 위한 유틸 클래스 작성

📌 JwtTokenProvider.java (JWT 생성 & 검증)

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

public class JwtTokenProvider {
    private final Key secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    private final long ACCESS_TOKEN_EXPIRATION = 1000 * 60 * 15;  // 15분
    private final long REFRESH_TOKEN_EXPIRATION = 1000 * 60 * 60 * 24 * 7;  // 7일

    // 🔹 Access Token 생성
    public String generateAccessToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION))
                .signWith(secretKey)
                .compact();
    }

    // 🔹 Refresh Token 생성
    public String generateRefreshToken() {
        return Jwts.builder()
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + REFRESH_TOKEN_EXPIRATION))
                .signWith(secretKey)
                .compact();
    }

    // 🔹 토큰 검증 메서드
    public boolean validateToken(String token) {
        try {
            Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }

    // 🔹 토큰에서 사용자 정보 추출
    public String getUsernameFromToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }
}

 

이제 Access Token & Refresh Token을 생성할 수 있음!
Access Token은 15분, Refresh Token은 7일로 설정


🔹 3. 로그인 API에서 JWT 발급 & 저장

📌 AuthController.java (로그인 API 구현)

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

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/auth")
public class AuthController {
    private final JwtTokenProvider jwtTokenProvider = new JwtTokenProvider();

    // 🔹 로그인 API
    @PostMapping("/login")
    public Map<String, String> login(@RequestParam String username) {
        String accessToken = jwtTokenProvider.generateAccessToken(username);
        String refreshToken = jwtTokenProvider.generateRefreshToken();

        // 클라이언트가 Refresh Token을 보관하도록 응답에 포함
        Map<String, String> response = new HashMap<>();
        response.put("accessToken", accessToken);
        response.put("refreshToken", refreshToken);
        return response;
    }
}

로그인 시 Access Token & Refresh Token을 함께 발급


🔹 4. 리프레시 토큰을 이용한 Access Token 갱신 API

📌 AuthController.java (토큰 갱신 API 추가)

@PostMapping("/refresh")
public Map<String, String> refresh(@RequestParam String refreshToken) {
    // Refresh Token 검증
    if (!jwtTokenProvider.validateToken(refreshToken)) {
        throw new RuntimeException("Invalid Refresh Token");
    }

    // 새로운 Access Token 발급
    String newAccessToken = jwtTokenProvider.generateAccessToken("User");

    Map<String, String> response = new HashMap<>();
    response.put("accessToken", newAccessToken);
    return response;
}

3️⃣ 결론: 리프레시 토큰을 활용한 인증 시스템의 장점

🔹 리프레시 토큰 적용으로 얻는 장점

보안성 유지: Access Token을 짧게 유지하면서도 재로그인 없이 갱신 가능
사용자 경험 향상: 일정 시간 후에도 로그인 유지 가능
서버 부담 감소: Access Token은 Stateless하므로, 세션을 관리할 필요 없음

🔹 추가적으로 고려할 점

  • Refresh Token 저장 방식:
    • 보안 강화를 위해 DB나 Redis에 저장하는 방법도 고려
    • 클라이언트가 Refresh Token을 보관하면 XSS/CSRF 공격 위험이 있음
  • 만료된 Refresh Token 관리:
    • Refresh Token이 탈취되었을 경우를 대비해 강제 로그아웃 기능 구현 필요
  • OAuth2와 통합:
    • OAuth2 인증 방식과 함께 적용하면 소셜 로그인 지원 가능

🎯 마무리: 스프링부트에서 리프레시 토큰을 적용하려면?

JWT 기반 인증 방식을 사용하면 서버 부담 없이 인증 가능!
Access Token은 짧게 설정하고, Refresh Token을 활용하면 사용자 경험 개선!
토큰 검증 API(/refresh)를 활용하여 토큰 갱신 자동화 가능!

🔥 이제 직접 코드 구현해보고, 보안 강화를 위해 Refresh Token을 DB에 저장하는 방법도 추가해보자! 🚀

반응형