반응형

React 버전을 최신 버전을 적용했더니 오픈소스가 호환이 되지 않는 항목들을 많이 경험할 수 있었습니다.

 

18.2.0 을 사용하고 있었는데

 

17.0.2 로 낮추고 사용하기로 결정했습니다.

 

버전을 낮추는 방법은 간단하더라고요

 

npm install react@^17.0.2 react-dom@17.0.2

원하는 버전이 있다면  17.0.2 를 다른버전으로 적용하면 됩니다.

 

그리고 서버를 재시작하면 아래와 같은 컴파일 실패 오류가 발생합니다.

 

Failed to compile.

Module not found: Error: Can't resolve 'react-dom/client' in 'C:\workspace\react\src'
ERROR in ./src/index.js 5:0-40
Module not found: Error: Can't resolve 'react-dom/client' in 'C:\workspace\react\src'

webpack compiled with 1 error

 

모듈을 찾을 수 없다는 건데 18버전에서 사용했던 react-dom/client 모듈을 찾을 수 없다는 오류인데

 

react-dom/client -->> react-dom 으로 변경해주시면 오류는 사라지고,

 

정상적으로 컴파일이 완료될 것입니다.

 

 

 

 

Uncaught TypeError: react_dom__WEBPACK_IMPORTED_MODULE_1__.createRoot is not a function

 

위 오류는 아래 소스를 변경합니다.

 

 

변경전
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <App/>
);

 

 

변경후

ReactDOM.render(
  <App/>,
  document.getElementById('root')
);

 

위와 같이 변경하면 버전 다운그레이드가 완료됩니다.

반응형
블로그 이미지

나남나여

일상 제품리뷰와 맛집/여행/사진을 좋아하고 IT 관련 프로그래밍 초급 & 고급 정보를 공유하는 블로그

,
반응형

spring mybatis mysql 설정 방법

 

database connection 연결정보를 설정하기 위해서 mybatis 를 사용한 케이스입니다.

 

datasource1 : mysql 설정방법

datasource2 : oracle 설정방법

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.2.xsd">
 
 
 	<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/sakila?useUnicode=yes&amp;characterEncoding=utf8" />
		<property name="username" value="admin" /> 
		<property name="password" value="1234" />
		<property name="validationQuery" value="select 1"/>
		<property name="testWhileIdle" value="true"/>
		<property name="timeBetweenEvictionRunsMillis" value="7200000"/>
 	</bean>
 
 	


 	<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
 		<property name="url" value="jdbc:oracle:thin:@localhost:1521/ORCL" />
 		<property name="username" value="admin" /> 
		<property name="password" value="1234" /> 
		<property name="validationQuery" value="select 1 from dual"/>
		<property name="testWhileIdle" value="true"/>
		<property name="timeBetweenEvictionRunsMillis" value="7200000"/>
 	</bean>
  
</beans>

 

 

 

driverClassName : JDBC 커넥션 시 어떤 드라이버를 사용할 것인지 명시

 

url : 연결 될 DB 의 ip 와 Service ID 또는 Service Name 설정

 

username, password : DB 접속정보 입력

 

validationQuery : JDBC 커넥션의 유효성을 해당 쿼리문을 실행하여 확인할 수 있다.

 

testWhileIdle : Evictor Thread 실행 시 커넥션 풀 안에 있는 유효상태의 커넥션을 대상으로 테스트 실행

 

timeBetweenEvictionRunsMillis : Evictor Thread 가 동작하는 간격을 의미한다. ( default : -1 )

 

반응형
블로그 이미지

나남나여

일상 제품리뷰와 맛집/여행/사진을 좋아하고 IT 관련 프로그래밍 초급 & 고급 정보를 공유하는 블로그

,
반응형

jmeter 의 webdriver 를 사용하여 selenium 을 사용하다보면

 

iframe 을 포함하고 있는 페이지의 동작이 필요한 경우가 발생하게 됩니다.

 

하지만 selenium 에서 iframe 에 있는 아이디나 tag, xpath, linkText 등등 여러가지를 사용해서

 

iframe 내에 있는 동작을 처리하려고 할 때 정상적으로 되지 않는 경우가 발생합니다.

 

 

<html lang="ko"><script src="chrome-extension://ljdobmomdgdljniojadhoplhkpialdid/page/prompt.js"></script><script src="chrome-extension://ljdobmomdgdljniojadhoplhkpialdid/page/runScript.js"></script><head>
	<link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon">
	<link rel="icon" href="/images/favicon.ico" type="image/x-icon">

	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=Edge">	
	
	<script type="text/javascript" src="/js/jquery/jquery-3.5.1.min.js"></script>
	<script type="text/javascript" src="/js/jquery/jquery.serializeObject.min.js"></script>	

	<title>Test</title>
    
    ....
	<body>
    ....
    <iframe id="iframe-1">
    #document
    <!DOCTYPE html>
    	<html>
        <head>
        <body>
        ....
        	....
            ....
            <div id="iframe_div">
            	....
                ....

 

위의 예시는 기본 html 내 iframe 이 속해있는 구조입니다.

 

이런 구조에서 iframe 내에 있는 iframe_div 를 조작하려고 하면 커서가 iframe 쪽으로 이동하지 않았기 때문에

 

로그도 남지 않고 아무런 반응이 일어나지 않는 경우가 있습니다.

 

그럼 ifrmae 쪽으로 커서를 이동해주어야 iframe 내에 있는

 

컴포넌트들이 동작을 할텐데 어떻게 해야하는지 알아보겠습니다.

 

 

var iframe = WDS.browser.findElement(org.openqa.selenium.By.xpath("//iframe[@name='iframe-1']"))
WDS.browser.switchTo().frame(iframe)

wait.until(ui.ExpectedConditions.visibilityOfElementLocated(org.openqa.selenium.By.id('iframe_div')))
WDS.browser.findElement(org.openqa.selenium.By.xpath("//div[@id='iframe_div']/div[4]/div/div/div/div[2]/span")).click();
WDS.browser.findElement(org.openqa.selenium.By.xpath("//div[@id='iframe_div']/div[27]/div/img")).click();

 

방법은 위와 같이 아주 간단합니다.

 

iframe 을 식별할 수 있는 iframe-1 을 선택할 수 있게 switchTo function 을 사용하면 간단하게 커서 이동이 됩니다.

 

그 후에는 iframe 내에 있는 객체들을 마음껏 사용할 수 있습니다

 

간단하게 사용할 수 있으니 테스트한번 해보시기 바랍니다.

반응형
블로그 이미지

나남나여

일상 제품리뷰와 맛집/여행/사진을 좋아하고 IT 관련 프로그래밍 초급 & 고급 정보를 공유하는 블로그

,
반응형

jMeter plugin webDriver 설치 및 사용방법

 

 

성능 테스트를 하기 위해 jMeter 를 설치하고 http request sampler 를 이용하여

 

테스트를 하고 있었는데 dynamic script 를 호출하여 CGI 프로그램을 실행해야하는 부분이 존재하였다.

 

웹페이지 안에 dynamic script 가 정상적으로 호출되지 않아

 

CGI 프로그램의 response 를 정상적으로 받지 못하는 상황이 발생.

 

어떻게 해야 정상적으로 프로그램을 짤 수 있을까 찾아보던 도중

 

jMeter plugin 중 webDriver 라는것이 존재한다는 사실을 확인하였다.

 

webDriver 를 사용하게 되면 기존에 http request Sampler 를 사용했던 것과는 달리

 

sampler 를 추가 했을 때 빈화면이 나와서 당황스러울수도 있다.

 

직접 소스코딩을 하라는 얘기인데 강력한 기능에는 강력한 권한이 부여되니 너무 걱정하지 않아도 된다.

 

사용해보고 어떻게 사용하는지 설치 및 사용방법에 대해 간단하게 정리해놓기로 한다.

 

jMeter 는 정상적으로 설치되었다는 가정하에 시작.

 

 

1. Options 메뉴의 Plugins Manager 선택

 

 

2. webdriver 라고 검색하면 selenium/WebDriver Support 항목을 체크 후  Apply Changes and Restart JMeter 버튼을 클릭한다.

 

 

플러그인이 정상적으로 설치되며, jmeter 가 재시작되게 된다.

 

 

3. Chrome Driver Config 및 WebDriver Sampler

 

이제 Thread Group 내 Chrome Driver Config 와 WebDriver Sampler 를 사용할 수 있게 되었다.

 

 

Chrome Driver Config

 

 

 

WebDriver Sampler

 

4. ChromeWebDriver 를 다운로드 받는다.

 

chromedriver.chromium.org/downloads

 

위 경로에 들어가서 받을 수 있다.

 

chrome web driver

 

현재 자신이 사용하고 있는 chrome browser 의 버전과 동일한 web driver 를 다운받아야 정상적으로 테스트를 할 수 있다. ( 그렇지 않으면 스크립트 오류가 발생하는 것을 확인함 )

 

 

 

 

다운 받은 chromedriver 의 exe 파일은 Chrome Driver Config 쪽에 등록해주면 기본적인 세팅은 끝

 

Chrome Driver Config 에서는 Use Chrome headless mode 를 사용할 수 있다.

 

headless mode 는 jMeter 를 run 시키면 크롬 브라우저가 실행되면서

 

내가 직접 작성한 내용이 브라우저에서 그대로 실행되는데

 

headless mode 를 체크 후 실행하면 back ground 에서 실행되게되니 부하기의 리소스를 덜 먹게 된다.

 

5. webDriver Sampler 소스를 입력

 

 

var pkg = JavaImporter(org.openqa.selenium);
var ui=JavaImporter(org.openqa.selenium.support.ui) 
var support_ui = JavaImporter(org.openqa.selenium.support.ui.WebDriverWait);

WDS.sampleResult.sampleStart()
WDS.browser.get("http://localhost:8080/index.aspx/?Param=aaa");

var wait = new support_ui.WebDriverWait(WDS.browser, 500);
wait.until(ui.ExpectedConditions.visibilityOfElementLocated(pkg.By.id('login_id')))    
WDS.browser.findElement(pkg.By.xpath("//div[@id='login_btn']/div[3]/div/img")).click();

wait.until(ui.ExpectedConditions.visibilityOfElementLocated(pkg.By.className('ui-menu')))
WDS.browser.findElement(pkg.By.linkText("new report")).click();
wait.until(ui.ExpectedConditions.visibilityOfElementLocated(pkg.By.name('menu-01')));
WDS.browser.findElement(pkg.By.id("FDOI5LBN053KNK39")).click();

var action = new org.openqa.selenium.interactions.Actions(WDS.browser)
action.moveToElement(WDS.browser.findElement(pkg.By.id("FDOI5LBN053KNK39"))).doubleClick().build().perform()
WDS.browser.findElement(pkg.By.id("execute")).click();


WDS.sampleResult.sampleEnd()

 

로컬에 설치해놓은 서버에 접근해서 화면을 조회하는 화면이다.

 

기본적인 개념은 webDriver 를 사용하면 브라우저가 해당 object 를 rendering 하는 시간이 소요되게 되는데

 

rendering 전에 object 를 찾으려고 하면 찾을 수 없으니 object 가 화면에 그려진 후 다음 작업을 진행되도록 처리하였다.

 

object 를 찾는 것은 xpath, id, name, class, linkText 를 이용하여 객체를 찾을 수 있다.

 

좀 더 스크립트를 쉽게 개발하기 위해서는

 

chrome 의 확장프로그램을 이용하여 recording 을 할 수 있는 Katalon Recorder 가 있지만

 

recorder 를 100% 믿을 수는 없는 것이 no such element: Unable to locate element 오류를 만날 수 있기 때문이다.

 

해결 방법은 위에 적어놓음.

 

다음에 다시 load test 를 하는 날에 다시 읽어볼 날이 오겠지~~

반응형
블로그 이미지

나남나여

일상 제품리뷰와 맛집/여행/사진을 좋아하고 IT 관련 프로그래밍 초급 & 고급 정보를 공유하는 블로그

,
반응형

 

 

tomcat 을 사용하면서 위와 같은 오류가 발생한 경우가 발생했습니다.

 

 

 

직역하자면 JDBC 드라이버 클래스 oracle.jdbc.driver.OracleDriver를 로드 할 수 없습니다. 라는 의미입니다.

 

 

환경은 솔루션에서 커스터마이징을 통해서 소스를 추가로 업로드 했는데

 

 

오류가 발생한 케이스였습니다.

 

 

문제를 해결하기 위해 구글링을 해봤더니

 

 

JDBC 오라클 드라이버가 없어서 발생한 오류였습니다.

 

 

JDBC 드라이버를 사용하는 jar 파일을 찾기 위해 오라클 클라이언트를 설치한 곳으로 이동하여

 

 

원하는 jar 파일을 가지고 왔습니다.

 

 

위치 : <%오라클 설치폴더%>\product\11.2.0\client_1\jdbc\lib

 

 

이 위치로 이동하면 ojdbc6.jar 파일이 존재하는데

 

 

사용하기 위한 소스에 라이브러리로 등록해주면 오류 해결.

 

 

솔루션이 정상적으로 구동되기 위해서는 서버를 재시작하는 수고가 더 들어갔습니다.

 

 

사용하는 버전이나 환경에 따라 ojdbc5.jar 파일이나 ojdbc14.jar 파일과 같이

 

 

파일명은 조금씩 다를 수 있으니

 

 

사용하고 있는 버전을 잘 확인 후 정확한 소스 반영하시길 권장드립니다.^^

 

 

해결이 안되면 같이 해결할 수 있게 댓글로 문의 주시면 같이 해결할 수 있는 방법 찾아보도록 할께요

 

 

반응형
블로그 이미지

나남나여

일상 제품리뷰와 맛집/여행/사진을 좋아하고 IT 관련 프로그래밍 초급 & 고급 정보를 공유하는 블로그

,
반응형

jquery 로 iframe form submit ( sample 포함 )




특정 페이지를 submit(호출)하기 위해

jsp 에서 iframe 을 사용했는데

iframe 의 src 에 넣은 link가

하필 보안에 위배되는 주소가 되어버렸습니다.



jsp 에서 iframe 에 사용한 src 를 어떻게 숨길지 고민하다

jqeury 를 사용해서 해당 페이지를 호출 후 

삭제하는 로직을 넣어보기로 했습니다.



변경전 jsp 구조샘플

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>TEST</title>
<link rel="stylesheet" type="text/css" href="./css/style.css">
<script type="text/javascript" src="./js/jquery.js"></script>
<script type="text/javascript" src="./js/index.js"></script>
<form id="frm" method="post" target="cgi">
<div>
---중략---
</div>
</form>    
<iframe name="iFrm" style="display: none;" src="https://tistory.com"></iframe>


iframe 에서 src 로 입력한 부분이 소스보기시 노출되어 보안문제 발생!

과감히 iframe 태그를 삭제하고 js 파일에서 작성하도록 합니다.



index.js 에서 jquery 를 이용한 iframe 생성

function init() {
	var iframe = $('');
	$( "body" ).append(iframe);
	var src = "https://tistory.com";
	iframe.attr('src',src).load(function(){
						$('#iFrm').remove()
						});
}




body 에 onload event 를 처리한 function 에 아래내용을 넣어줬습니다.


iframe 태그를 load 한 후 바로 삭제 했으니 남아있는게 없게 되었습니다!





궁금한점 있으면 댓글 작성해주세요!

반응형
블로그 이미지

나남나여

일상 제품리뷰와 맛집/여행/사진을 좋아하고 IT 관련 프로그래밍 초급 & 고급 정보를 공유하는 블로그

,
반응형



AES 암호화 방식을 통한 DBCP 암호화




암호화 처리는 어떤 데이터를 암호화 하느냐에 따라

일방향 암호화 처리를 할 것인지

양방향 암호화 처리를 할 것인지 결정하게 됩니다.



일방향암호화 : 사용자비밀번호와 같이 시스템관리자도 복호화가 필요없이 비교만 하면 되는 경우

양방향암호화 : 사용자이름, 휴대폰번호, 계좌번호 등 복호화하여 시스템운영상 확인이 필요한 경우


복호화가 필요한 경우는 암호화 했던 비밀키를 입력하여 풀어냅니다.



이번 포스팅에서는 tomcat 을 was 로 사용하는 경우

server.xml 에 평문으로 입력된 DB접속정보가 노출되어

2차 피해는 막자는 취지에서 샘플 소스를 공유합니다.



준비


AES 암호화를 위한 필요라이브러리

https://commons.apache.org/proper/commons-codec/download_codec.cgi



이클립스를 사용하는 경우 

commons-codec-1.11-bin.zip 파일 다운로드 받은 후 commons-codec-1.11.jar 를 java build path 에 등록합니다.




아래는 server.xml 에 등록된 DB 접속정보입니다.

username , password , url 정보가 평문으로 입력되어 있어 

인증되지 않은 사용자가 해당 파일을 오픈 했을 때 서버정보를 쉽게 알 수 있게 됩니다.







목표

username , password , url 와 같은 평문 저장을 원치 않는 속성을 암호화 처리


암호화 처리 방식 : AES-256

( SEED 방식도 많이 쓰니 다음에 정리하겠습니다..)




STEP 1.

라이브러리 등록 : commons-codec-1.11.jar


파일 다운로드 경로 : https://commons.apache.org/proper/commons-codec/download_codec.cgi


commons-codec-1.11-bin.zip 파일을 받아 압축을 풀면

해당 jar 라이브러리 파일이 존재하는데

Java Build Path에 등록합니다.





STEP 2

평문 데이터를 암호화 및 복호화 function 제공 ( AES256Util.java )



package com.encrypt;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

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");
	}
}


작업 내용 : 암호화 / 복호화 처리 함수 제공






STEP 3

서버정보 암호화 내용 확인 ( TestMain.java )




package com.encrypt;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;

public class TestMain {

	public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, GeneralSecurityException {
		AES256Util aes = new AES256Util("testestestestses");   // 암호화 키 16자리
			
		// 암호화 된 내용
		System.out.println("scott : " + aes.encrypt("scott"));  
		System.out.println("tiger : " + aes.encrypt("tiger"));
		  
	}

}


작업내용 : STEP 2 에서 작성한 함수를 main 을 통해서 테스트할 수 있습니다.



TestMain.java 실행결과



scott : BxoN1jurrKiXrlSSvf0/ng==
tiger : JcHanmccsCwU4Z4NpnYQKg==



복호화 했을 때 입력했던 값을 받을 수 있다면 성공!



System.out.println(aes.decrypt("BxoN1jurrKiXrlSSvf0/ng=="));
System.out.println(aes.decrypt("JcHanmccsCwU4Z4NpnYQKg=="));



STEP 4


암호화 된 정보를 복호화 하는 factory 를 생성


DBCP 의 기본은 org.apache.commons.dbcp.BasicDataSourceFacroty 를 사용하고 있는데

해당 class 파일을 decompile 후 아래와 같이 customizing 했습니다.



package com.encrypt;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import javax.sql.DataSource;

import org.apache.tomcat.dbcp.dbcp.BasicDataSource;

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("testestestestses");

	  return aes.decrypt(encryptStr);

  }
}






위 소스에서 중요내용

username, password, url 에 해당하는 부분을 복호화하도록 변경



변경전 : dataSource.setPassword(value);
변경후 : dataSource.setPassword(decryptDBCPProperty(value));


눈치빠른 분들은 아시겠지만

server.xml 에서 입력된 username, password , url 을 암호화 하는 부분이었습니다.

( 위 3가지 정보 중 필요한 부분만 암호화 처리해도 됩니다. )


STEP 5

server.xml 에 암호화 된 내용으로 개인정보 변경






여기서 중요한 부분은 STEP 4 에서 만든 factory 를 지정하여

DBCP 할 때 사용할 수 있도록 합니다.

default 값은 BasicDataSourceFactory 로 별도로 지정해주지 않으면

tomcat-dbcp.jar 에 있는 내용을 사용하게 되니

반드시 우리가 만든 factory 를 설정해주시기 바랍니다.




여기까지 작업하면 해당 내용이 암호화 처리가 됩니다!


궁금한점이나 안되는 부분있으면 댓글 달아주세요^^


반응형
블로그 이미지

나남나여

일상 제품리뷰와 맛집/여행/사진을 좋아하고 IT 관련 프로그래밍 초급 & 고급 정보를 공유하는 블로그

,
반응형