|
* JWT 구성
JWT는 Header, Payload, Signature 구조로 이루어져 있다. 각 요소는 다음 기능을 수행한다.
- JWT의 특징은 내부 정보를 단순 BASE64 방식으로 인코딩하기 때문에 외부에서 쉽게 디코딩 할 수 있다.
- 외부에서 열람해도 되는 정보를 담아야하며, 토큰 자체의 발급처를 확인하기 위해서 사용한다.
- 지폐와 같이 외부에서 그 금액을 확인하고 금방 외형을 따라서 만들 수 있지만 발급처에 대한 보장 및 검증은 확실하게 해야하는 경우에 사용한다. 따라서 토큰 내부에 비밀번호와 같은 값 입력 금지
- 토큰의 마지막 부분은 디지털 서명입니다. 이 부분은 JWT 토큰을 공유하는 당사자가 내부자이고 신뢰할 수 있지만 웹에서 공개할 수 없는 경우 선택 사항일 수 있습니다.
- 하지만 이 토큰을 모든 사용자가 오픈 웹에서 사용하는 클라이언트 애플리케이션에 공유하는 경우 권한, 사용자 이름 등과 같은 헤더 및 본문 값을 아무도 변경하지 않았는지 확인해야 합니다.
- 아무도 네트워크의 데이터를 변조하지 않았는지 확인하기 위해 토큰이 처음 생성될 때 콘텐츠의 서명을 보낼 수 있습니다. 서명 부분을 만들려면 인코딩된 헤더, 인코딩된 페이로드, 비밀, 헤더에 지정된 알고리즘을 가져와 서명해야 합니다.
JWT 암호화 방식
암호화 키 저장
암호화 키는 하드코딩 방식으로 구현 내부에 탑재하는 것을 지양하기 때문에 변수 설정 파일에 저장한다.
application.properties
spring.jwt.secret=암호화키
JWTUtil
@Component
public class JWTUtil {
private SecretKey secretKey;
// application.properties에 설정한 secret 값을 가져와서 secretKey에 할당
public JWTUtil(@Value("${spring.jwt.secret}")String secret) {
secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), Jwts.SIG.HS256.key().build().getAlgorithm());
}
// 사용자 이름 가져오기
public String getUsername(String token) {
return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().get("username", String.class);
}
// 사용자 권한 가져오기
public String getRole(String token) {
return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().get("role", String.class);
}
// 토큰 만료 여부 확인
public Boolean isExpired(String token) {
return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().getExpiration().before(new Date());
}
// 토큰 생성
public String createJwt(String username, String role, Long expiredMs){
return Jwts.builder()
.claim("username", username)
.claim("role", role)
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + expiredMs))
.signWith(secretKey)
.compact();
}
}
|