
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
package com.takensoft.common.util;
import com.takensoft.cms.mber.vo.MberAuthorVO;
import com.takensoft.cms.mber.vo.MberVO;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import jakarta.servlet.http.Cookie;
import java.nio.charset.StandardCharsets;
import java.util.*;
/**
* @author : takensoft
* @since : 2025.01.22
* @modification
* since | author | description
* 2025.01.22 | takensoft | 최초 등록
*
* JWT 토큰 생성 및 검증, 쿠키 생성 등의 유틸리티
*/
@Component
public class JWTUtil {
private static SecretKey JWT_SECRET_KEY;
/**
* @param secret - JWT 서명을 위한 키 (application.yml에서 값을 읽어 옴)
*
* 기본 생성자
*/
public JWTUtil(@Value("${jwt.secret}")String secret) {
this.JWT_SECRET_KEY = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), Jwts.SIG.HS256.key().build().getAlgorithm());
}
/**
* @param category 토큰의 카테고리 정보 (Authorization, refresh)
* @param mbrId 사용자 ID
* @param lgnId 로그인 ID
* @param mbrNm 사용자 이름
* @param roles 사용자 권한 목록
* @param expiredMs 토큰 만료 시간 (밀리초)
* @return 생성된 JWT 토큰 (String)
*
* JWT 토큰 생성
*/
public String createJwt(String category, String mbrId, String lgnId, String mbrNm, List<String> roles, long expiredMs) {
return Jwts.builder()
.claim("category", category)
.claim("mbrId", mbrId)
.claim("lgnId", lgnId)
.claim("mbrNm", mbrNm)
.claim("roles", roles)
.issuedAt(new Date(System.currentTimeMillis())) // 토큰 발행 시간
.expiration(new Date(System.currentTimeMillis() + expiredMs)) // 토큰 소멸 시간
.signWith(JWT_SECRET_KEY)
.compact();
}
/**
* @param key 쿠키 키 값
* @param value 쿠키 값
* @param time 쿠키의 생명주기 (초 단위)
* @return 생성된 Cookie 객체
*
* 쿠키 생성
*/
public Cookie createCookie(String key, String value, int time) {
// 쿠키 생성
Cookie cookie = new Cookie(key, value);
cookie.setMaxAge(time); // 생명주기
//cookie.setSecure(true); // https 통신을 할 경우 true로 사용
cookie.setPath("/"); // 쿠키 적용 범위
cookie.setHttpOnly(true); // front에서 script로 접근 방지
return cookie;
}
public String getCategory(String token) {
return Jwts.parser().verifyWith(JWT_SECRET_KEY).build().parseSignedClaims(token).getPayload().get("category", String.class);
}
// 접속자 토큰 기반 회원 아이디 추출
public String getMbrId(String token) {
return Jwts.parser().verifyWith(JWT_SECRET_KEY).build().parseSignedClaims(token).getPayload().get("mbrId", String.class);
}
// 접속자 토큰 기반 로그인 아이디 추출
public String getLgnId(String token) {
return Jwts.parser().verifyWith(JWT_SECRET_KEY).build().parseSignedClaims(token).getPayload().get("lgnId", String.class);
}
// 접속자 토큰 기반 회원명 추출
public String getMbrNm(String token) {
return Jwts.parser().verifyWith(JWT_SECRET_KEY).build().parseSignedClaims(token).getPayload().get("mbrNm", String.class);
}
// 접속자 토큰 기반 권한정보 추출
public List<MberAuthorVO> getRoles(String token) {
// 토큰에서 권한 정보를 가져옴
Claims claims = Jwts.parser().verifyWith(JWT_SECRET_KEY).build().parseSignedClaims(token).getPayload();
List<HashMap> roles = claims.get("roles", List.class);
List<MberAuthorVO> authorList = new ArrayList<MberAuthorVO>();
if (roles != null && !roles.isEmpty()) {
for(Map role : roles) {
MberAuthorVO mberAuthor = new MberAuthorVO();
mberAuthor.setAuthrtCd(role.get("authority").toString());
authorList.add(mberAuthor);
}
}
return authorList;
}
// 토큰 소멸 여부
public Boolean isExpired(String token) {
return Jwts.parser().verifyWith(JWT_SECRET_KEY).build().parseSignedClaims(token).getPayload().getExpiration().before(new Date());
}
// 토큰 만료 시간
public Date getExpired(String token) {
return Jwts.parser().verifyWith(JWT_SECRET_KEY).build().parseSignedClaims(token).getPayload().getExpiration();
}
// 로그인 사용자 아이디 조회
public String getWriter() {
String mbrId = null;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication != null && authentication.isAuthenticated()) {
Object principal = authentication.getPrincipal();
if(principal instanceof UserDetails) mbrId = ((MberVO) authentication.getPrincipal()).getMbrId();
}
return mbrId;
}
/**
* @param tkn JWT 토큰 문자열
* @param knd 조회할 데이터의 종류 (예: ctgry, userId, loginId 등)
* @return 조회된 클레임 데이터 (종류에 따라 String, Date, List 등으로 반환)
* @throws IllegalArgumentException 유효하지 않은 knd 값일 경우 예외 발생
*
* 클레임 조회
*/
public Object getClaim(String tkn, String knd) {
Claims claims = Jwts.parser()
.verifyWith(JWT_SECRET_KEY)
.build()
.parseSignedClaims(tkn)
.getPayload();
switch (knd) {
case "category":
return claims.get("category", String.class);
case "mbrId":
return claims.get("mbrId", String.class);
case "lgnId":
return claims.get("lgnId", String.class);
case "mbrNm":
return claims.get("mbrNm", String.class);
case "roles":
// roles 클레임에서 사용자 권한 정보를 파싱
List<Map<String, Object>> roles = claims.get("roles", List.class);
List<MberAuthorVO> authorList = new ArrayList<>();
if(roles != null && !roles.isEmpty()) {
for(Map<String, Object> role : roles) {
MberAuthorVO userAuthor = new MberAuthorVO(role.get("authority").toString());
authorList.add(userAuthor);
}
}
return authorList;
case "isExpired":
// 토큰 만료 여부 반환
return claims.getExpiration().before(new Date());
case "expired":
// 토큰 만료 시간 반환
return claims.getExpiration();
default:
// 유효하지 않는 knd 처리
throw new IllegalArgumentException("Invalid knd : " + knd);
}
}
}