본문 바로가기
JAVA

JNDI (db정보 암호화 AES256) [SPRING]

by MMXVI 2023. 1. 31.
728x90
반응형
SMALL

 

1.암호화 부분

AES256Util.java

 

public class AES256Util {
	private String iv;
	private Key keySpec;

	public AES256Util(String key) throws UnsupportedEncodingException {
		this.iv = key.substring(0, 16);
		byte[] keyBytes = new byte[16];
		byte[] b = key.getBytes("UTF-8");
		int len = b.length;
		if (len > keyBytes.length) {
			len = keyBytes.length;
		}
		System.arraycopy(b, 0, keyBytes, 0, len);
		SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
		this.keySpec = keySpec;
	}

	public String encrypt(String str)
			throws NoSuchAlgorithmException, GeneralSecurityException, UnsupportedEncodingException {
		Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
		c.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes()));
		byte[] encrypted = c.doFinal(str.getBytes("UTF-8"));
		String enStr = new String(Base64.encodeBase64(encrypted));
		return enStr;
	}

	public String decrypt(String str)
			throws NoSuchAlgorithmException, GeneralSecurityException, UnsupportedEncodingException {
		Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
		c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes()));
		byte[] byteStr = Base64.decodeBase64(str.getBytes());
		return new String(c.doFinal(byteStr), "UTF-8");
	}

1-2 암호화 test 부분

 

메소드를 추가해서 Sysout 찍히는 로그를 확인한다.

암호화 확인부분

16비트 이상이라는 오류가 나올시 

AES256UTIL aes =new ("aes25612345678910") 부분 16자리 이상으로 맞춰주면된다.

 

@RequestMapping("/test.do") 
	public static void main(String[] args)
			throws UnsupportedEncodingException, NoSuchAlgorithmException, GeneralSecurityException {
				AES256Util aes = new AES256Util("AES25612345678910");
				// 암호화 키 16자리 // 암호화 된 내용 
				System.out.println("userName : " + aes.encrypt("db.userName 넣는부분"));			
				System.out.println("password : " + aes.encrypt("db.password 넣는부분"));
				System.out.println("url : " + aes.encrypt("dburl넣는부분"));
				
				
			}

2.복호화 DB 접속 실행 부분

  맨밑에 decryptDBCPProperty 이쪽 부분을 추가해줬습니다.

public class EncryptDataSourceFactory implements ObjectFactory {
	private static final String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";
	private static final String PROP_DEFAULTREADONLY = "defaultReadOnly";
	private static final String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";
	private static final String PROP_DEFAULTCATALOG = "defaultCatalog";
	private static final String PROP_DRIVERCLASSNAME = "driverClassName";
	private static final String PROP_MAXACTIVE = "maxActive";
	private static final String PROP_MAXIDLE = "maxIdle";
	private static final String PROP_MINIDLE = "minIdle";
	private static final String PROP_INITIALSIZE = "initialSize";
	private static final String PROP_MAXWAIT = "maxWait";
	private static final String PROP_TESTONBORROW = "testOnBorrow";
	private static final String PROP_TESTONRETURN = "testOnReturn";
	private static final String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";
	private static final String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
	private static final String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";
	private static final String PROP_TESTWHILEIDLE = "testWhileIdle";
	private static final String PROP_PASSWORD = "password";
	private static final String PROP_URL = "url";
	private static final String PROP_USERNAME = "username";
	private static final String PROP_VALIDATIONQUERY = "validationQuery";
	private static final String PROP_VALIDATIONQUERY_TIMEOUT = "validationQueryTimeout";
	private static final String PROP_INITCONNECTIONSQLS = "initConnectionSqls";
	private static final String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";
	private static final String PROP_REMOVEABANDONED = "removeAbandoned";
	private static final String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";
	private static final String PROP_LOGABANDONED = "logAbandoned";
	private static final String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";
	private static final String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";
	private static final String PROP_CONNECTIONPROPERTIES = "connectionProperties";
	private static final String[] ALL_PROPERTIES = { "defaultAutoCommit", "defaultReadOnly",
			"defaultTransactionIsolation", "defaultCatalog", "driverClassName", "maxActive", "maxIdle", "minIdle",
			"initialSize", "maxWait", "testOnBorrow", "testOnReturn", "timeBetweenEvictionRunsMillis",
			"numTestsPerEvictionRun", "minEvictableIdleTimeMillis", "testWhileIdle", "password", "url", "username",
			"validationQuery", "validationQueryTimeout", "initConnectionSqls", "accessToUnderlyingConnectionAllowed",
			"removeAbandoned", "removeAbandonedTimeout", "logAbandoned", "poolPreparedStatements",
			"maxOpenPreparedStatements", "connectionProperties" };

	public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
		if ((obj == null) || (!(obj instanceof Reference))) {
			return null;
		}
		Reference ref = (Reference) obj;
		if (!"javax.sql.DataSource".equals(ref.getClassName())) {
			return null;
		}
		Properties properties = new Properties();
		for (int i = 0; i < ALL_PROPERTIES.length; i++) {
			String propertyName = ALL_PROPERTIES[i];
			RefAddr ra = ref.get(propertyName);
			if (ra != null) {
				String propertyValue = ra.getContent().toString();
				properties.setProperty(propertyName, propertyValue);
			}
		}
		return createDataSource(properties);
	}

	public static DataSource createDataSource(Properties properties) throws Exception {
		BasicDataSource dataSource = new BasicDataSource();
		String value = null;
		value = properties.getProperty("defaultAutoCommit");
		if (value != null) {
			dataSource.setDefaultAutoCommit(Boolean.valueOf(value).booleanValue());
		}
		value = properties.getProperty("defaultReadOnly");
		if (value != null) {
			dataSource.setDefaultReadOnly(Boolean.valueOf(value).booleanValue());
		}
		value = properties.getProperty("defaultTransactionIsolation");
		if (value != null) {
			int level = -1;
			if ("NONE".equalsIgnoreCase(value)) {
				level = 0;
			} else if ("READ_COMMITTED".equalsIgnoreCase(value)) {
				level = 2;
			} else if ("READ_UNCOMMITTED".equalsIgnoreCase(value)) {
				level = 1;
			} else if ("REPEATABLE_READ".equalsIgnoreCase(value)) {
				level = 4;
			} else if ("SERIALIZABLE".equalsIgnoreCase(value)) {
				level = 8;
			} else {
				try {
					level = Integer.parseInt(value);
				} catch (NumberFormatException e) {
					System.err.println("Could not parse defaultTransactionIsolation: " + value);
					System.err.println("WARNING: defaultTransactionIsolation not set");
					System.err.println("using default value of database driver");
					level = -1;
				}
			}
			dataSource.setDefaultTransactionIsolation(level);
		}
		value = properties.getProperty("defaultCatalog");
		if (value != null) {
			dataSource.setDefaultCatalog(value);
		}
		value = properties.getProperty("driverClassName");
		if (value != null) {
			dataSource.setDriverClassName(value);
		}
		value = properties.getProperty("maxActive");
//		if (value != null) {
//			dataSource.setMaxActive(Integer.parseInt(value));
//		}
//		value = properties.getProperty("maxIdle");
		if (value != null) {
			dataSource.setMaxIdle(Integer.parseInt(value));
		}
		value = properties.getProperty("minIdle");
		if (value != null) {
			dataSource.setMinIdle(Integer.parseInt(value));
		}
		value = properties.getProperty("initialSize");
		if (value != null) {
			dataSource.setInitialSize(Integer.parseInt(value));
		}
		value = properties.getProperty("maxWait");
//		if (value != null) {
//			dataSource.setMaxWait(Long.parseLong(value));
//		}
		value = properties.getProperty("testOnBorrow");
		if (value != null) {
			dataSource.setTestOnBorrow(Boolean.valueOf(value).booleanValue());
		}
		value = properties.getProperty("testOnReturn");
		if (value != null) {
			dataSource.setTestOnReturn(Boolean.valueOf(value).booleanValue());
		}
		value = properties.getProperty("timeBetweenEvictionRunsMillis");
		if (value != null) {
			dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(value));
		}
		value = properties.getProperty("numTestsPerEvictionRun");
		if (value != null) {
			dataSource.setNumTestsPerEvictionRun(Integer.parseInt(value));
		}
		value = properties.getProperty("minEvictableIdleTimeMillis");
		if (value != null) {
			dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(value));
		}
		value = properties.getProperty("testWhileIdle");
		if (value != null) {
			dataSource.setTestWhileIdle(Boolean.valueOf(value).booleanValue());
		}
		value = properties.getProperty("password");
		if (value != null) {
			dataSource.setPassword(decryptDBCPProperty(value));
		}
		value = properties.getProperty("url");
		if (value != null) {
			dataSource.setUrl(decryptDBCPProperty(value));
		}
		value = properties.getProperty("username");
		if (value != null) {
			dataSource.setUsername(decryptDBCPProperty(value));
		}
		value = properties.getProperty("validationQuery");
		if (value != null) {
			dataSource.setValidationQuery(value);
		}
		value = properties.getProperty("validationQueryTimeout");
		if (value != null) {
			dataSource.setValidationQueryTimeout(Integer.parseInt(value));
		}
		value = properties.getProperty("accessToUnderlyingConnectionAllowed");
		if (value != null) {
			dataSource.setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(value).booleanValue());
		}
		value = properties.getProperty("removeAbandoned");
//		if (value != null) {
//			dataSource.setRemoveAbandoned(Boolean.valueOf(value).booleanValue());
//		}
//		value = properties.getProperty("removeAbandonedTimeout");
		if (value != null) {
			dataSource.setRemoveAbandonedTimeout(Integer.parseInt(value));
		}
		value = properties.getProperty("logAbandoned");
		if (value != null) {
			dataSource.setLogAbandoned(Boolean.valueOf(value).booleanValue());
		}
		value = properties.getProperty("poolPreparedStatements");
		if (value != null) {
			dataSource.setPoolPreparedStatements(Boolean.valueOf(value).booleanValue());
		}
		value = properties.getProperty("maxOpenPreparedStatements");
		if (value != null) {
			dataSource.setMaxOpenPreparedStatements(Integer.parseInt(value));
		}
		value = properties.getProperty("initConnectionSqls");
		if (value != null) {
			StringTokenizer tokenizer = new StringTokenizer(value, ";");
			dataSource.setConnectionInitSqls(Collections.list(tokenizer));
		}
		value = properties.getProperty("connectionProperties");
		if (value != null) {
			Properties p = getProperties(value);
			Enumeration e = p.propertyNames();
			while (e.hasMoreElements()) {
				String propertyName = (String) e.nextElement();
				dataSource.addConnectionProperty(propertyName, p.getProperty(propertyName));
			}
		}
		if (dataSource.getInitialSize() > 0) {
			dataSource.getLogWriter();
		}
		return dataSource;
	}

	private static Properties getProperties(String propText) throws Exception {
		Properties p = new Properties();
		if (propText != null) {
			p.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes()));
		}
		return p;
	}

	private static String decryptDBCPProperty(String encryptStr)
			throws UnsupportedEncodingException, NoSuchAlgorithmException, GeneralSecurityException {
		AES256Util aes = new AES256Util("aeskey123456789810");
						
		// 암호화 키 16자리 // 암호화 된 내용보려면
       System.out.println("userName : " + aes.encrypt("db정보"));
		
		return aes.decrypt(encryptStr);
	}

 

3.환경설정 

 

 

3-1 context-dataSource.xml 

*JNDI : dataSource와 동시 사용 불가 둘중 하나 주석 처리*

=====================================================================================

<!-- 환경설정 기본정보를 globals.properties 에서 참조하도록 propertyConfigurer 설정  -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:/egovProps/globals.properties</value>
            </list>
        </property>
    </bean>

추가 

<jee:jndi-lookup jndi-name="${Globals.JNDI}" id="dataSource" resource-ref="true" />

 

3-2.server.xml 

tomcat -conf 폴더에 server.xml 수정 

<Host> 밑에 

밑에 코드 추가

<Context docBase="" path="" reloadable="true">
<Resource name="${global.JNDI}설정한 ID" auth="Container" 
factory="egovframework.com.utl.sim.service.EncryptDataSourceFactory" >
type="javax.sql.DataSource" 
username="암호화된 db.UserName" 
password="암호화된password 입력" 
driverClassName="해당 db drverclassname 입력" 
url="암호화된 url 평문체로 넣어도됨" maxActive="10" maxIdle="10" maxWait="-1"/>
</Context>

</Host>

4.실행

확인후   암호화 복호화 파일

System.out.println("userName : " + aes.encrypt(""));

 정보 지우고 적용 

 

순서 

class 파일 추가  --> 암호화정보확인 -->context-datasource.xml , server.xml  수정 -->실행  확인  

728x90
반응형
LIST

댓글