본문 바로가기

웹서비스

[Java] XML Validation 비활성화 하기

출처 : http://blog.handkstory.net/15

최근 대량의 XML파일을 파싱할 일이 있었습니다. 처음에는 Python으로 구현을 했지만 이 애플리케이션이 계속 수정이 되면서 제가 짜놓고도 무슨 코드인지 모르겠더군요 -_-;;(Python도 좋은 언어지만 저같은 개발자가 살짝 정줄 놓는 순간 Python의 유연성은 독약이 되지요.. ㅡ,.ㅡ;; ) 그래서 고심끝에 Java로 애플리케이션을 다시 구현하였습니다. Python으로 개발하다가 Java로 갈아타니 처음엔 그 깐깐한 성격때문에 Python이 그리워 지긴 했지만 그래도 다음에서 인턴할 때 자바로 조금은 체계적으로 개발하는 방법을 배운덕택에 코드를 수정하더라도 그리 어렵지 않게 수정할 수 있게 되었습니다.

XML 데이터가 많아서 파싱에 소요되는 시간이 많기 때문에 구현은 로컬에서하고, 실행은 서버에서 screen을 사용하여 하였습니다. 잘만 돌아가던 애플리케이션이 어느날인가 부터 예외를 발생시키기 시작하더군요. 예외를 내뿜는 코드는 아래와 같습니다.

DocumentBuilderFactory docBuilderFactory =

DocumentBuilderFactory.newInstance();

DocumentBuilder docBuilder;

Document doc = null;

try {

docBuilder = docBuilderFactory.newDocumentBuilder();

File f = new File(filePath+String.valueOf(id)+".xml");

doc = docBuilder.parse(f); //요부분에서 예외발생

} catch (Exception e) {

e.printStackTrace();

}


javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:808)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1112)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1139)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123)

at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:418)

...

XML 데이터는 로컬에 파일 형태로 저장되어 있고 애플리케이션에서는 그 어떤 통신도 하지 않는데 SSLHandshake는 무엇이며, Remote host는 또 왜 튀어나올까 고심을 많이 했습니다. 열심히 구글신에게 물어보니 SSL 인증서 문제일 것이라 하여 열심히 인증과 관련된 부분을 열심히 뒤졌지만 결국 답을 얻지 못하였습니다. 최후의 보루로 제가 다음에서 인턴할 때 사고칠때마다 뒷수습을 담당해주신 황현석 선배님에게 자문을 요청했고 제가 2일동안 낑낑대며 고생한 문제를 2시간 만에 해결해주셨습니다.(능력자이십니다. =_=b)
여기서 문제가 된 부분은 XML 헤더 파일에 Validation을 위한 DTD 파일의 URL이 있었고, 제 애플리케이션에서 각각의 XML 파일을 읽어올 때 마다 해당 DTD파일에 대한 리퀘스트를 서버로 날렸고, 이를 일종의 공격으로 인식한 서버에서 저희 측 서버를 Block 해버렸더군요 -_-;;;;;
해결책은 DocumentBuilderFactory 에서 DocumentBuilder를 생성할 때 Validation을 비활성화 시켜 주는 것입니다.

DocumentBuilderFactory docBuilderFactory =

DocumentBuilderFactory.newInstance();

DocumentBuilder docBuilder;

Document doc = null;

try{

docBuilderFactory.setValidating(false);

docBuilderFactory.setFeature("http://xml.org/sax/features/namespaces", false);

docBuilderFactory.setFeature("http://xml.org/sax/features/validation", false);

docBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);

docBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

docBuilder = docBuilderFactory.newDocumentBuilder();

File f = newFile(filePath+String.valueOf(id)+".xml");

doc = docBuilder.parse(f);

} catch(Exception e) {

e.printStackTrace();

}

저희측을 Block한 서버의 관리자에게는 메일을 보내서 몰라서 그랬으니 Block을 해제해 달라 하니 바로 해제해 주시더군요. 참으로 난감한 경험이였습니다. -_-;; 저처럼 외부와 통신하지않는 XML DOM 파서에서 SSLHandshakeException을 만나시는 분들에게 도움이 되길 바랍니다.. (아직 이런 경험이 없으신 분들도 대량의 XML을 처리할 때는 다른 서버에 피해가 가지 않도록 Validation을 끄는게 좋겠죠? Validation은 필요할때만 사용하도록 합시다!ㅠㅠ)

'웹서비스' 카테고리의 다른 글

[JSP] XML 읽기  (0) 2010.06.30
SOAP의 개념 (간단예제)  (0) 2010.06.30
[JAVA] XML-RPC  (0) 2010.06.30
HTTP/XML 기반  (0) 2010.06.30
[JAVA] XML 통신  (0) 2010.06.28