신입사원분을 대상으로 하는 OJT 과정 중 "Spring Boot 기반 개발" 과정을 담당하게 되었다.
이에 간단한 자료와 예제 프로젝트를 작성하여 OJT를 진행하였다.
application.properties (yml)에 대한 설명을 하던 중 다음과 같은 질문을 받았다.
"저 application.properties 내 DB 정보는 외부에 유출이 되면 안될텐데, 저걸 저렇게 그대로 작성해도 괜찮나요?"
application.properties 내 정보는 특정 라이브러리를 사용하면 암호화할 수 있다는 것 정도는 알고 있었다. 하지만 그 라이브러리가 무엇인지, 어떻게 사용할 수 있는지는 미처 알지 못했었다. 그래서 위 질문에 제대로 된 답변을 내놓지 못했다.
OJT가 끝난 후 위에서 받은 질문은 언제든지 현업에서도 받을 수 있는 질문이고, 언제든 요구사항으로 들어올 수 있는 사항이라는 생각이 들었다. 그래서 구글링을 통해 방법을 찾아놓았으며, 언제든 프로젝트에 적용할 수 있도록 소스코드를 저장해놓고자 포스팅을 작성했다.
application.properties 파일에 암호화를 하기 위해 가장 먼저 해야할 작업은 pom.xml에 암호화 라이브러리를 추가하는 것이다.
pom.xml 내 dependencies에 다음 dependency를 추가한다.
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
그 후 추가한 디펜던시를 설정해준다.
방법은 아래와 같다.
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.jasypt.salt.RandomSaltGenerator;
import org.jasypt.salt.SaltGenerator;
import org.jasypt.salt.StringFixedSaltGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EncryptConfig {
private String encryptKey = "test-key"; // 인코딩용 키 생성
private String fixedSalt = "test-salt";
@Bean(name="StringEncryptor")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(encryptKey); //암호화할 때 사용하는 키
config.setAlgorithm("PBEWithMD5AndDES"); //암호화 알고리즘
config.setKeyObtentionIterations(1000); //반복할 해싱 회수
config.setPoolSize(1); //인스턴스 pool
// SALT 지정
// 1. 랜덤 방식
//config.setSaltGenerator(saltGenerator())
// 2. 고정 방식
config.setSaltGenerator(new StringFixedSaltGenerator(fixedSalt));
config.setStringOutputType("base64"); // 인코딩 방식 지정
encryptor.setConfig(config);
return encryptor;
}
@Bean(name="SaltGenerator")
public SaltGenerator saltGenerator() {
return new RandomSaltGenerator();
}
}
위에서 알고리즘 설정은 PBEWithMD5AndDES 외에도 여러 알고리즘이 설정 가능하다.
어떤 알고리즘이 가능한지 보는 방법은 Test 코드를 통해 아래의 코드로 확인이 가능하다.
@Test
void getAlgorithmList() {
logger.info("@@@ DigestAlgorithms \t: {}", AlgorithmRegistry.getAllDigestAlgorithms());
logger.info("@@@ PBEAlgorithms \t: {}", AlgorithmRegistry.getAllPBEAlgorithms());
}
여기까지 완료되었다면 이제 DB내 데이터들을 암호화해야 한다.
해당하는 데이터는 spring.datasource의 URL, USERNAME, PASSWORD이다.
암호화는 test 코드로 돌려서 암호화된 String을 복사하여 사용하면 되는데, 이상하게 @Autowired로 StringEncryptor를 불러오면 에러가 발생하여 다음과 같이 작성하였다.
@Test
void getEncryptDbInfo() {
StandardPBEStringEncryptor pbeEnc = new StandardPBEStringEncryptor();
String url="jdbc:mariadb://....:3306/....";
String userName="....";
String password="....";
pbeEnc.setAlgorithm("PBEWithMD5AndDES"); // Encoder 설정 시와 같은 알고리즘으로 구성
pbeEnc.setPassword("test-key"); // Encoder 설정 시와 같은 키로 구성
pbeEnc.setSaltGenerator(new StringFixedSaltGenerator("test-salt"));
logger.info("@@@url \t: {}", pbeEnc.encrypt(url));
logger.info("@@@userName \t: {}", pbeEnc.encrypt(userName));
logger.info("@@@password \t: {}", pbeEnc.encrypt(password));
}
위의 테스트 코드를 실행하면 Logger에 의해 암호화된 URL, USERNAME, PAWWSORD가 콘솔에 출력되는데, 해당 암호화된 String을 복사하여 application.yml에 ENC() 태그안에 넣어준다.
spring.datasource.url=ENC(wj....f1wUyIk)
spring.datasource.username=ENC(g4A....4=)
spring.datasource.password=ENC(QzK....A==)
여기까지 설정했다면 이제 프로젝트가 실행되며 암호화된 정보가 복호화되어 Spring 내부에 들어가게 된다.
위 과정이 정상적으로 진행된다면 JPA를 통한 CRUD가 정상적으로 이루어져야 한다.
테스트를 위해 id, password로 이루어진 간단한 테이블을 생성한 후 Domain, Repository 클래스를 작성하여 아래의 테스트 코드를 돌려보자.
@Autowired testRepository repo;
@Test
void dbCrud() {
testDomain td = new testDomain("123", "456");
repo.save(td);
logger.info("@@@ SAVED");
testDomain returnTd = repo.findById("123").orElse(null);
assertEquals(returnTd.getId(), td.getId());
logger.info("@@@ LOADED");
repo.delete(td);
logger.info("@@@ DELETED");
}
에러 없이 위의 로그들이 잘 출력된다면 성공한 것이다.
'실습 > 리눅스 서버 + 스프링 부트' 카테고리의 다른 글
[Shell Script] 쉘 스크립트 문법 (0) | 2022.08.16 |
---|---|
JPA 페이징 (0) | 2022.07.25 |
Spring WebFlux Filter (0) | 2022.07.25 |
Spring Security rememberMe (자동 로그인) (0) | 2022.07.25 |
Ehcache (0) | 2022.04.02 |