📘JWT 사용하기 위한 초기세팅 방법
JWT 기초 정리
// security - 같이 추가해준다.
implementation 'org.springframework.boot:spring-boot-starter-security'
// jwt
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'
//토큰 생성, 추출, 검증 담당 클래스
@Component
public class JwtTokenUtils {
//JWT 서명에 사용할 비밀 키 저장 변수
private Key key;
// HS256 알고리즘용 키 자동 생성 -> 테스트용
@PostConstruct
protected void init() {
this.key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
}
HS256 알고리즘에 맞게 생성되며, 이 키를 나중에 토큰 서명(signing)과 검증(verify)에 사용//토큰 유지 시간 (1시간)
private final long tokenValidityInMilliseconds = 1000 * 60 * 60;
//Access Token : 로그인 후 API 호출에 사용
public String createAccessToken(Long userId) {
return jwtTokenUtils.createToken(userId, tokenValidityInMilliseconds/4); // 15분
}
//Refresh Token : Access Token 이 만료됐을 때 재발급 요청에 사용
public String createRefreshToken(Long userId) {
return jwtTokenUtils.createToken(userId, tokenValidityInMilliseconds * 168); // 일주일
}
//토큰 생성 메서드
public String createToken(Long userId, long validityInMilliseconds) {
//JWT 의 데이터 영역 부분. userId 는 기본 필드
Claims claims = Jwts.claims().setSubject(userId.toString());
//현재 시간과 토큰의 만료시간 설정
Date now = new Date();
Date validity = new Date(now.getTime() + validityInMilliseconds);
return Jwts.builder()
.setClaims(claims) // claims set
.setIssuedAt(now) // 토큰 생성 시각
.setExpiration(validity) // 만료시각
.signWith(key, SignatureAlgorithm.HS256) //비밀 키로 서명(HS256 알고리즘 사용)
.compact(); // JWT 문자열로 압축(최종 토큰 생성)
}
Access 토큰은 인증에 사용, Refresh 토큰은 Access 토큰 재발급에 사용된다.Access 토큰은 유지시간을 짧게(15분 정도) 하고, Refresh 토큰은 유지시간을 길게(일주일 정도) 설정한다.// 토큰에서 userId 추출
public Long getUserIdByToken(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(key) // 비밀키 설정
.build()
.parseClaimsJws(token) // 토큰 파싱 후 서명 검증
.getBody(); //Payload(Claims) 가져옴
return Long.parseLong(claims.getSubject()); // 토큰에 저장된 정보(userId)
}
userId(PK)값만 들어있고 해당 정보를 가져온다.//토큰 유효성 검증(key, 만료, 유효 시작, 형식)
public boolean isValidToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(key) // 비밀키 설정
.build()
.parseClaimsJws(token); //// 토큰 파싱 후 서명 검증
return true;
} catch (JwtException | IllegalArgumentException e) {
return false; //보안상 에러메세지 최소화
}
}