심층 기술 분석 (Deep Tech Dive)/Spring Boot 심층 분석

Spring Boot에서 JWT와 Redis를 이용한 인증 구현하기

코린이ch 2024. 10. 17. 22:48

소개

현대 웹 애플리케이션에서 보안은 매우 중요한 요소입니다. 이 포스트에서는 Spring Boot 애플리케이션에서 JWT(JSON Web Token)와 Redis를 사용하여 안전하고 효율적인 인증 시스템을 구현하는 방법을 알아보겠습니다.

프로젝트는 다음과 같은 환경에서 구축되었습니다:

  • Spring Boot
  • Java
  • Gradle
  • Docker
  • Redis
  • GitHub Actions (CI/CD)

인증 프로세스 개요

구현할 인증 프로세스는 다음과 같습니다:

  1. 클라이언트의 로그인 요청
  2. 아이디/비밀번호 검증 후 Access Token과 Refresh Token 발급
  3. Refresh Token은 Redis에 저장하고, 클라이언트에 두 토큰 모두 응답
  4. 클라이언트의 API 호출 시, Access Token이 만료되었다면 Refresh Token을 검증하여 새로운 Access Token 재발급

의존성 추가

build.gradle 파일에 다음 의존성을 추가합니다:

implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

// JWT 관련 추가 의존성
implementation 'com.sun.xml.bind:jaxb-impl:4.0.1'
implementation 'com.sun.xml.bind:jaxb-core:4.0.1'
implementation 'javax.xml.bind:jaxb-api:2.4.0-b180830.0359'

Redis 설정

Docker Compose를 사용하여 Redis 환경을 구축합니다. docker-compose.yml 파일의 예시:

version: '3'
services:
  redis:
    image: redis:latest
    ports:
      - "6379:6379"

Spring Boot 애플리케이션에서 Redis 설정:

@Configuration
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private int redisPort;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(redisHost, redisPort);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        return template;
    }
}

JWT 구현

JWT 생성 및 검증을 위한 유틸리티 클래스를 만듭니다:

@Component
public class JwtTokenProvider {
    @Value("${jwt.secret}")
    private String jwtSecret;

    @Value("${jwt.accessTokenValidityInMilliseconds}")
    private long accessTokenValidityInMilliseconds;

    @Value("${jwt.refreshTokenValidityInMilliseconds}")
    private long refreshTokenValidityInMilliseconds;

    public String createAccessToken(Authentication authentication) {
        // Access Token 생성 로직
    }

    public String createRefreshToken() {
        // Refresh Token 생성 로직
    }

    public boolean validateToken(String token) {
        // 토큰 검증 로직
    }

    // 기타 필요한 메소드들...
}

사용자 인증 서비스

사용자 인증을 처리할 서비스를 구현합니다:

@Service
public class AuthService {
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final JwtTokenProvider jwtTokenProvider;
    private final RedisTemplate<String, Object> redisTemplate;

    // 생성자 주입

    public TokenDto login(LoginDto loginDto) {
        // 로그인 로직 구현
    }

    public TokenDto reissue(TokenRequestDto tokenRequestDto) {
        // 토큰 재발급 로직 구현
    }

    // 기타 필요한 메소드들...
}

Redis를 이용한 Refresh Token 관리

Redis에 Refresh Token을 저장하고 관리하는 로직을 구현합니다:

@Service
public class RefreshTokenService {
    private final RedisTemplate<String, Object> redisTemplate;
    private final JwtTokenProvider jwtTokenProvider;

    // 생성자 주입

    public void saveRefreshToken(String username, String refreshToken) {
        // Refresh Token을 Redis에 저장
    }

    public String getRefreshToken(String username) {
        // Redis에서 Refresh Token 조회
    }

    public void deleteRefreshToken(String username) {
        // Redis에서 Refresh Token 삭제
    }
}

인증 컨트롤러 구현

인증 관련 엔드포인트를 처리할 컨트롤러를 구현합니다:

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    private final AuthService authService;

    // 생성자 주입

    @PostMapping("/login")
    public ResponseEntity<TokenDto> login(@RequestBody LoginDto loginDto) {
        // 로그인 처리
    }

    @PostMapping("/reissue")
    public ResponseEntity<TokenDto> reissue(@RequestBody TokenRequestDto tokenRequestDto) {
        // 토큰 재발급 처리
    }

    // 기타 필요한 엔드포인트들...
}

보안 설정

Spring Security 설정을 통해 인증 및 인가를 구현합니다:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final JwtTokenProvider jwtTokenProvider;

    // 생성자 주입

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 보안 설정 구현
    }

    // 기타 필요한 설정들...
}

결론

이 글에서는 Spring Boot 애플리케이션에서 JWT와 Redis를 사용하여 안전하고 효율적인 인증 시스템을 구현하는 방법을 살펴보았습니다. 이 방식은 서버의 상태를 최소화하면서도 보안성을 높일 수 있는 장점이 있습니다.

향후 개선 사항으로는 토큰 암호화, 멀티 디바이스 지원, 그리고 보안 감사 로깅 등을 고려해볼 수 있습니다.