mybatis를 사용하는 경우 특정 필드의 데이터를 암복호화 하는 경우의 처리방법이다.
환경: JDK11, Springboot 2.7.x
<!-- pom.xml -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
// mybatisConfig abstract class
import java.io.IOException;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
public abstract class MybatisConfig {
public static final String TYPE_ALIAS_PACKAGE = "dev.com";
public static final String CONFIG_PATH = "classpath:config/mybatis.xml";
protected abstract void dbConfigureSqlSessionFactory(SqlSessionFactoryBean sessionFactoryBean, DataSource dataSource) throws IOException;
}
// ComMybatisConfig
import java.io.IOException;
import javax.sql.DataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
@MapperScan(basePackages = "dev.com", annotationClass = ComDBMapper.class, sqlSessionFactoryRef = "comSqlSessionFactory")
public class ComMybatisConfig extends MybatisConfig {
private static final String MAPPER_PATH_FOR_COM = "classpath*:mapper/dev/com/**/*Mapper.xml";
@Bean(name = "comSqlSessionFactory")
@Primary
SqlSessionFactory comSqlSessionFactory(@Qualifier("comDataSource") DataSource ds) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
dbConfigureSqlSessionFactory(sqlSessionFactoryBean, ds);
return sqlSessionFactoryBean.getObject();
}
@Override
protected void dbConfigureSqlSessionFactory(SqlSessionFactoryBean sessionFactoryBean, DataSource dataSource) throws IOException {
// interceptor 설정 시작
Interceptor[] interceptor = {new MybatisFieldConverterInterceptor(new FieldValueEncryptAndDecryptConverter()) };
sessionFactoryBean.setPlugins(interceptor);
// interceptor 설정 종료
PathMatchingResourcePatternResolver pathResolver = new PathMatchingResourcePatternResolver();
sessionFactoryBean.setDataSource(dataSource);
sessionFactoryBean.setTypeAliasesPackage(TYPE_ALIAS_PACKAGE);
sessionFactoryBean.setConfigLocation(pathResolver.getResource(CONFIG_PATH));
sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_PATH_FOR_COM));
}
}
사용할 mapper interface 이다.
// ComDBMapper
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ComDBMapper {
}
이제 intercetor를 만들어보자. 인터페이스를 만들고 implement 해본다.
// MybatisFieldValueConverter
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public interface MybatisFieldValueConverter {
Object convertParameterValue(final Field field, final Method getter, final Method setter, final String key, final Object value);
Object revertParameterValue(final Field field, final Method getter, final Method setter, final String key, final Object value);
Object convertResultSetValue(final Field field, final Method getter, final Method setter, final String key, final Object value);
}
// FieldValueEncryptAndDecryptConverter
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FieldValueEncryptAndDecryptConverter implements MybatisFieldValueConverter {
// 암복호화 대상 체크
private boolean checkField(String fieldName) {
// 암복호화 대상여부 체크 로직 작성
return true;
}
@Override
public Object convertParameterValue(final Field field, final Method getter, final Method setter, final String key, final Object value) {
// 암호화
if (value instanceof String) {
boolean isEncryptTarget = checkField(key);
if (isEncryptTarget) {
return (String) "암호화" + key;
}
}
return value;
}
@Override
public Object revertParameterValue(final Field field, final Method getter, final Method setter, final String key, final Object value) {
// 복호화
return convertResultSetValue(field, getter, setter, key, value);
}
@Override
public Object convertResultSetValue(final Field field, final Method getter, final Method setter, final String key, final Object value) {
// 복호화
if (value instanceof String) {
boolean isDecryptTarget = checkField(key);
if (isDecryptTarget) {
return (String) "복호화" + key;
}
}
return value;
}
}
대상 필드 체크는 대상 리스트를 불러와서 대상인지 비교하는 방식으로 구현한다.
...
Thanks to JDS
728x90
'개발 > java' 카테고리의 다른 글
| springboot redis client 만들기 (1) | 2024.01.08 |
|---|---|
| Logbook 으로 access log 남기기 (2) | 2024.01.04 |
| JPA EntityListener로 multi JpaRepository save (1) | 2022.09.07 |
| Runtime에서 annotation attribute 변경 - influxDB @Measurement 공통 DTO 만들기 (1) | 2022.09.07 |
| vscode debugger에서 java.lang.ExceptionInInitializerError 잡기 (0) | 2022.09.07 |