JWT(Json Web Token)은 사용자 인증, 데이터 교환에 사용되는 토큰 기반 인증 방식
즉,
서버-클라이언트 간의 보안 인증서 역할을 함.
JWT란?
JSON 형식으로 구성된, 3부분으로 이루어진 문자열.
- Header: 토큰의 타입, 알고리즘 정보 포함
- Payload: 토큰에 포함된 데이터(사용자 ID, 권한 정보 등)
- Signature: 토큰의 무결성을 검증하기 위한 서명
예:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJleHAiOjE2NzQ5NjM4MDB9.dXN3iQjXryGvQo_rivmnDNfQnMJy9Q0hDIpg9hswKmA
JWT를 활용한 로그인 호출
1. 사용자 로그인 요청
- 사용자가 아이디, 비밀번호를 입력하고 로그인 요청을 보냄.
2. 서버에서 인증 후, JWT 발급
- 서버는 DB에서 사용자 정보를 확인하고, 인증 성공시 JWT 생성함.
- 이 JWT는 사용자 정보를 암호화하고, 클라이언트로 반환함.
3. 클라이언트가 JWT 저장
- 클라이언트(앱)은 반환된 JWT를 로컬 스토리지 or 세션에 저장함.
4. 추후 요청에 JWT 포함
- 클라이언트는 서버에 요청할 때마다 Header에 JWT를 포함하여 인증을 진행함.
5. 서버가 JWT 검증
- 서버는 JWT가 변조되지 않았는지 확인하고, 유효 기간이 남아있으면 요청을 처리함.
Spring Boot에서 JWT 구현하기
1. JWT 라이브러리 추가
<!-- build.gradle.kts -->
implementation("io.jsonwebtoken:jjwt-api:0.11.5")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5")
2. 토큰 생성 및 검증 클래스
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "your-256-bit-secret-key"; // 환경 변수로 관리 권장
private static final Key key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
private static final long EXPIRATION_TIME = 1000 * 60 * 60; // 1시간
// 토큰 생성
public static String generateToken(String userId) {
return Jwts.builder()
.setSubject(userId)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(key, SignatureAlgorithm.HS256)
.compact();
}
// 토큰 검증
public static String validateToken(String token) {
try {
Claims claims = Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
} catch (JwtException e) {
return null; // 유효하지 않은 토큰
}
}
}
3. 로그인 컨트롤러
@RestController
@RequestMapping("/auth")
public class AuthController {
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
// 사용자를 데이터베이스에서 인증 (여기서는 생략)
String userId = "exampleUser"; // 인증된 사용자 ID
// JWT 생성
String token = JwtUtil.generateToken(userId);
return ResponseEntity.ok(new LoginResponse(token));
}
@GetMapping("/secure")
public ResponseEntity<?> secureEndpoint(@RequestHeader("Authorization") String authHeader) {
// JWT 검증
String token = authHeader.replace("Bearer ", "");
String userId = JwtUtil.validateToken(token);
if (userId == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
return ResponseEntity.ok("Secure data for user: " + userId);
}
}