이전 프로젝트 들에서는 JPA를 통해 사용자 데이터를 추가/수정/조회 시 @Query를 통해 SQL문을 작성해야만 했다.
전화번호 같은 개인정보 등을 DB에 저장 시 암호화된 데이터로 저장해야 하기 때문이었다. 이를 위해서는 Service 단에서 암/복호화를 수행 후 DB에 작업을 하는 방법이나 mysql AES_ENCRYPT를 통해 명령을 수행하는 방법을 사용했다.
이번에 Converter를 통해 Annotation만으로 손쉽게 암/복호화를 수행하는 방법을 찾게 되어 글을 작성하게 되었다.
@Converter 란?
엔티티의 데이터를 변환하여 데이터에 저장할 수 있는 기능
주로 개인정보나 암/복호화 해야하는 정보, 날짜를 원하는 방식으로 저장하기 위해 사용한다.
위 글에서는 전화번호의 암/복호화 수행을 하는 Class와 해당 Class의 암복호화 Method를 사용하여 데이터를 변환하는 Converter를 예시로 설명하겠다.
DatabaseAesEncryptUtil (암복호화 CLASS)
프로젝트에서 MYSql의 AES_ENCRYPT를 통해 데이터를 암호화 하였으므로 아래의 AES 암/복호화 방식을 사용했다.
import org.apache.commons.codec.binary.Hex;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class DatabaseAesEncryptUtil {
// 암호화
public static String encryption(String text, String dbKey) {
try {
Cipher cipher = Cipher.getInstance("AES");
byte[] key = new byte[16];
int i = 0;
for(byte b : dbKey.getBytes()) {
key[i++%16] ^= b;
}
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
return new String(Hex.encodeHex(cipher.doFinal(text.getBytes("UTF-8")))).toUpperCase();
} catch(Exception e) {
return text;
}
}
// 복호화
public static String decryption(String encryptedText, String dbKey) {
try {
Cipher cipher = Cipher.getInstance("AES");
byte[] key = new byte[16];
int i = 0;
for(byte b : dbKey.getBytes()) {
key[i++%16] ^= b;
}
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
return new String(cipher.doFinal(Hex.decodeHex(encryptedText.toCharArray())));
} catch(Exception e) {
return encryptedText;
}
}
}
AesEncDecConverter (암복호화 컨버터)
Override된 convertToDatabaseColumn가 Entity -> Database로 넣을 때,
convertToEntityAttribute가 Database -> Entity로 입력될 때 수행하는 메서드이다.
위 작성한 class를 통해 암/복호화 된 데이터를 반환한다.
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
@Converter
public class AesEncDecConverter implements AttributeConverter<String, String> {
private static dbKey = "암호화키";
@Override
public String convertToDatabaseColumn(String data){
return (data != null) ? DatabaseAesEncryptUtil.encryption(data, dbKey) : "";
}
@Override
public String convertToEntityAttribute(String data){
return (data != null) ? DatabaseAesEncryptUtil.decryption(data, dbKey) : "";
}
}
Member (Entity)
Jpa 테이블 Entity이다. @Convert Annotation을 이용해 Converter class를 등록해주면 해당 컬럼을 이용할 때 Converter method를 통해 데이터를 변환한다.
@Setter
@Getter
@Entity
@Table(name = "TB_MEMBER")
public class Member {
// 회원 일련번호
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_seq")
private Long memberSeq;
// 휴대폰번호
@Convert(converter = AesEncDecConverter.class)
@Column(name = "mobile_no")
private String mobileNo;
}
MemberRepo (repository)
mobileNo를 통한 데이터 조회 시 아래와 같이 메서드를 선언해주는 것만으로도 쉽게 복호화된 데이터를 가져올 수 있다.
@Repository
public interface MemberRepo extends JpaRepository<Member, Long> {
Member findByMobileNo(String mobileNo);
}
★ 지적사항이나 피드백은 언제나 환영입니다.
'프로그래밍 언어 > JAVA, SPRING' 카테고리의 다른 글
[SPRING BOOT] Actuator (0) | 2024.07.17 |
---|---|
[SPRING BOOT] 자동 설정 기능 (0) | 2024.07.17 |
SPRING 파헤치기 #2 - SOLID (0) | 2023.09.22 |
SPRING 파헤치기 #1 - SPRING FRAMEWORK (0) | 2023.09.22 |
어노테이션 @Valid와 @Validated (3) | 2023.09.11 |