JPA를 사용해 MongoDB를 연동하는 과정에서 MongoDB 내에 값을 암호화해야 하는 경우가 있다.

이에 spring-data-mongodb-encrypt 라는 암호화 모듈 제공파일을 사용하여 구현하게 되었다. (링크)

 

※사용 전 숙지사항

DB에 저장하기 전이나 불러온 후에는 값이 복호화된 상태로 존재하기 때문에, 응용 내에서도 암호화된 상태로 유지가 필요하다면 별도의 암호화 툴을 사용하는 것이 좋다.

 

pom.xml

Spring Boot 전용 MongoDB JPA 및 MongoDB 암호화 모듈을 추가한다.

<!-- Spring Data JPA - MongoDB -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
 
<!-- Spring Data JPA - MongoDB Encrypt -->
<dependency>
  <groupId>com.bol</groupId>
  <artifactId>spring-data-mongodb-encrypt</artifactId>
  <version>2.4.4</version>
</dependency>
 
 

 

MongoDBConfiguration.java

MongoDB JPA가 Spring Boot용 모듈이므로, application.properties나 application.yaml이 아닌 Java Config로 별도로 설정이 필요하다.

이 때, 기본적인 MongoDB 연동 과정 또한 마찬가지로 Spring Boot JPA 단에서 자체적으로 이루어지기 때문에 Java Config 생성 시에 가이드에 나온것처럼 AbstractMongoClientConfiguration 클래스를 상속받지 않도록 주의해야 한다.

@Configuration
public class MongoDBConfiguration {
 
  private static final byte[] oldKey = Base64.getDecoder().decode("cUzurmCcL+K252XDJhhWI/A/+wxYXLgIm678bwsE2QM="); // 키 값은 임의로 변경하여 사용한다.
  private static final byte[] secretKey = Base64.getDecoder().decode("hqHKBLV83LpCqzKpf8OvutbCs+O5wX5BPu3btWpEvXA="); // 마찬가지로, 변경하여 사용한다.
 
 
  @Bean
  public CryptVault cryptVault() {
    return new CryptVault()
      .with256BitAesCbcPkcs5PaddingAnd128BitSaltKey(0, oldKey)
      .with256BitAesCbcPkcs5PaddingAnd128BitSaltKey(1, secretKey)
      .withDefaultKeyVersion(1);      
  }
 
  @Bean
  public CachedEncryptionEventListener encryptionEventListener(CryptVault cryptVault) {
    return new CachedEncryptionEventListener(cryptVault);
  }
 
}

 

MyDTO.java

DTO용 클래스를 선언한다. 상단에 선언된 Lombok 애노테이션은 생략 가능하다.

@Getter 
@Setter 
@SuperBuilder
@NoArgsConstructor
@ToString
public class MyDTO {
 
  private String userId;
 
  @Encrypted
  private String password;
 
}
 
 
 

 

MyEntity.java

MyDTO를 상속하는 엔티티 클래스로, MyDTO의 @Encrypted가 선언된 password 설정을 유지한 상태로 가져오게 되어 MongoDB에 Insert하면 암호화된 값을 저장하게 된다.

마찬가지로 상단의 Lombok 애노테이션은 생략이 가능하며, 굳이 MyDTO를 상속받지 않고 따로 엔티티 클래스 내에 @Encrypted가 붙은 필드를 선언하여 사용해도 된다.

@Getter
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@ToString @Document(collection = "account")
public class MyEntity extends MyDTO { 
 
  @Id private String id;
 
}