JWT 인증 및 Redis 통합 가이드

프로젝트 구성 단계별 안내

1. 프로젝트 생성

Java 8을 기준으로 새 프로젝트를 생성합니다.

2. Maven 설정 및 의존성 추가

pom.xml에 필요한 의존성을 추가합니다.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.7.0</version>
    </dependency>
</dependencies>

3. 환경 변수 설정

resources/application.properties 파일에 다음 내용을 추가합니다.

server.port=9999
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.timeout=10000

4. 테스트 컨트롤러 구현

간단한 API 테스트를 위한 컨트롤러를 작성합니다.

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping("/test")
    public String test() {
        return "테스트 성공";
    }
}

5. JWT 유틸리티 클래스 개발

JWT 생성 및 검증을 처리하는 도구 클래스를 만듭니다.

import io.jsonwebtoken.*;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;

public class JwtUtil {
    private static final String SECRET = "mySecretKey";

    public static String createToken(String subject, long ttlMillis) {
        SecretKey key = generalKey();
        Date now = new Date();
        Date expDate = new Date(now.getTime() + ttlMillis);

        return Jwts.builder()
                  .setSubject(subject)
                  .setIssuedAt(now)
                  .setExpiration(expDate)
                  .signWith(SignatureAlgorithm.HS256, key)
                  .compact();
    }

    public static Claims parseToken(String token) throws Exception {
        SecretKey key = generalKey();
        return Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
    }

    private static SecretKey generalKey() {
        byte[] encodedKey = Base64.decodeBase64(SECRET);
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
    }
}

6. 사용자 모델 정의

사용자 정보를 관리하기 위한 데이터 클래스를 작성합니다.

import java.util.List;

public class Member {
    private Integer id;
    private String username;
    private String password;
    private List<String> roles;

    // Getter와 Setter 생략
}

7. 로그인 컨트롤러 구현

로그인 요청을 처리하고 토큰을 발급하는 컨트롤러를 작성합니다.

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AuthController {

    @PostMapping("/login")
    public String login(@RequestBody Member member) {
        if ("admin".equals(member.getUsername()) && "password".equals(member.getPassword())) {
            String token = JwtUtil.createToken(member.getUsername(), 1000 * 60); // 1분 유효
            return "Bearer " + token;
        }
        return "로그인 실패";
    }
}

8. 인터셉터 설정

요청 권한 검사를 위한 인터셉터를 구현합니다.

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String authHeader = request.getHeader("Authorization");

        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        try {
            String token = authHeader.substring(7);
            JwtUtil.parseToken(token);
            return true;
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return false;
        }
    }
}

9. 인터셉터 등록

인터셉터를 애플리케이션에 적용합니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}

태그: spring-boot jwt Redis

7월 6일 16:10에 게시됨