JSP/SERVLET
2018.03.31 / 16:24

[Java] Apache Commons HttpClient·Î SSL Åë½ÅÇϱâ

º½ÀÌ
Ãßõ ¼ö 263

* apache httpclient 4.4 ÀÌ»ó ¹öÀü

import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import javax.net.ssl.SSLContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;

HttpClientBuilder httpClientBuilder = HttpClients.custom();

SSLContext sslcontext = SSLContexts.custom()
    .useProtocol("SSL")
// .loadTrustMaterial(null, new TrustSelfSignedStrategy())
    .loadTrustMaterial(null, new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {
            return true;
        }
    }).build();

httpClientBuilder.setSSLHostnameVerifier(new NoopHostnameVerifier()).setSSLContext(sslcontext);

CloseableHttpClient httpClient = httpClientBuilder.build();
httpClient.execute();



* apache httpclient 4.3 ÀÌÇÏ ¹öÀü

import javax.net.ssl.SSLContext;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

SSLContext sslcontext = SSLContexts.custom()
    .useSSL()
    .loadTrustMaterial(null, new TrustSelfSignedStrategy())
/*
    .loadTrustMaterial(null, new TrustStrategy() {
        @Override
        public boolean isTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws java.security.cert.CertificateException {
            return true;
        }
    })
*/
    .build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

CloseableHttpClient httpClient = HttpClients.custom()
    .setSSLSocketFactory(sslsf)
    .build();

httpClient.execute();




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


Ãâó : http://comphy.iptime.org/user/wordpress/?p=81


Apache Commons HttpClient´Â JDK 1.4ºÎÅÍ µîÀåÇÑ Java Secure Socket Extension (JSSE)¸¦ ±â¹ÝÀ¸·Î SSL (¶Ç´Â TLS) »óÀÇ HTTP (HTTP/S) Åë½Å¿¡ ´ëÇÑ Áö¿øÀ» Á¦°øÇÑ´Ù. Commons HttpClient¸¦ ÀÌ¿ëÇÑ HTTP/S Åë½Å ¹æ¹ýÀ» »ìÆ캸ÀÚ.

1. Commons HttpClient »ç¿ëÇϱâ
ÀϹÝÀûÀ¸·Î Commons HttpClientÀÇ HTTP Åë½ÅÀº ¾Æ·¡¿Í °°´Ù.

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
// import org.apache.commons.httpclient.methods.PostMethod;

public class HttpClientSample {

    public static void main(String[] args) {

        HttpClient httpclient = new HttpClient();
        GetMethod httpget = new GetMethod("http://www.java2go.net/");
        // PostMethod httppost = new 
        // PostMethod("https://www.java2go.net/nopage.html");

        try {
            int statusCode = httpclient.executeMethod(httpget);

            System.out.println("Response Status Code: " + statusCode);
            System.out.println("Response Status Line: " + httpget.getStatusLine());
            System.out.println("Response Body: \n" 
                    + httpget.getResponseBodyAsString());

            if (statusCode == HttpStatus.SC_OK) {
                // if (statusCode >= 200 && statusCode < 300) {
                System.out.println("Success!");
            } else {
                System.out.println("Fail!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpget.releaseConnection();
        }
    }
}


Á¤»óÀûÀÎ °æ¿ì °á°ú´Â ¾Æ·¡¿Í °°´Ù.

Response Status Code: 200
Response Status Line: HTTP/1.1 200 OK
Response Body: 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Java2go.net</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

... »ý·« ...

</body>
</html>
Success!


½ÇÆÐÇÑ °æ¿ì °á°ú´Â ¾Æ·¡¿Í °°´Ù.

Response Status Code: 404
Response Status Line: HTTP/1.1 404 Not Found
Response Body: 
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>404 Not Found</TITLE>
</HEAD><BODY>
<H1>Not Found</H1>
The requested URL /nopage.html was not found on this server.<P>
<HR>
<ADDRESS>Apache/1.3.37p3 Server at java2go.net Port 80</ADDRESS>
</BODY></HTML>

Fail!


2. SSL Åë½Å°ú Trusted CA ÀÎÁõ¼­ µî·ÏÇϱâ
JSSE°¡ ¿Ã¹Ù¸£°Ô ¼³Ä¡µÇ¾ú´Ù¸é, ±âº»ÀûÀ¸·Î HTTP/S Åë½Åµµ ÀÏ¹Ý HTTP Åë½Å°ú °°ÀÌ À§¿Í °°Àº  Äڵ带 ±×´ë·Î »ç¿ëÇÒ ¼ö ÀÖ´Ù. ´Ü, ÀÌ °æ¿ì¿¡ ¼­¹ö ½ÎÀÌÆ® ÀÎÁõ¼­°¡ Ŭ¶óÀ̾ðÆ®ÂÊ¿¡ ½Å·ÚÇÏ´Â ÀÎÁõ¼­·Î¼­ ÀÎ½ÄµÉ ¼ö ÀÖ¾î¾ß ÇÑ´Ù. ±×·¸Áö ¾ÊÀ¸¸é ¾Æ·¡¿Í °°Àº SSL handshake ¿À·ù°¡ ¹ß»ýÇÑ´Ù.

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
No trusted certificate found
at com.sun.net.ssl.internal.ssl.BaseSSLSocketImpl.a(DashoA12275)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA12275)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA12275)
at com.sun.net.ssl.internal.ssl.SunJSSE_az.a(DashoA12275)
at com.sun.net.ssl.internal.ssl.SunJSSE_az.a(DashoA12275)
at com.sun.net.ssl.internal.ssl.SunJSSE_ax.a(DashoA12275)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA12275)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.j(DashoA12275)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA12275)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(DashoA12275)
... »ý·« ...
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
at sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:304)
at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:107)
at sun.security.validator.Validator.validate(Validator.java:202)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(DashoA12275)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(DashoA12275)
... 17 more


JDK¿¡ ÀÇÇØ Á¦°øµÇ¾îÁö´Â Java Standard Trust Keystore´Â ${JAVA_HOME}/jre/lib/security/cacerts¿¡ À§Ä¡ÇÑ´Ù. ÀÌ cacerts Å°½ºÅä¾î ÆÄÀÏ¿¡ ´ë»ó ¼­¹öÀÇ SSL ½ÎÀÌÆ® ÀÎÁõ¼­¸¦ ¹ßÇàÇÑ ±â°üÀÇ CA ÀÎÁõ¼­°¡ ½Å·ÚÇÏ´Â ÀÎÁõ¼­·Î µî·ÏµÇ¾î ÀÖ¾î¾ß ÇÑ´Ù. ´ÙÀ½°ú °°ÀÌ keytool.exe¸¦ »ç¿ëÇÏ¿© Å°½ºÅä¾î¿¡ µî·ÏµÈ ½Å·ÚÇÏ´Â ÀÎÁõ¼­ ¸ñ·ÏÀ» Á¶È¸ÇÒ ¼ö ÀÖ´Ù.

C:\jdk1.4.2\jre\lib\security>keytool -list -v -keystore cacerts
Enter keystore password: changeit

Keystore type: jks
Keystore provider: SUN

Your keystore contains 52 entries

Alias name: verisignclass3g2ca
Creation date: Jun 16, 2004
Entry type: trustedCertEntry

Owner: OU=VeriSign Trust Network, OU="(c) 1998 VeriSign, Inc. - For authorized
use only", OU=Class 3 Public Primary Certification Authority - G2, O="VeriSign,
Inc.", C=US
Issuer: OU=VeriSign Trust Network, OU="(c) 1998 VeriSign, Inc. - For authorized
use only", OU=Class 3 Public Primary Certification Authority - G2, O="VeriSign,
Inc.", C=US
Serial number: 7dd9fe07cfa81eb7107967fba78934c6
Valid from: Mon May 18 09:00:00 KST 1998 until: Wed Aug 02 08:59:59 KST 2028
Certificate fingerprints:
MD5: A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9
SHA1: 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F


*******************************************
*******************************************


Alias name: entrustclientca
Creation date: Jan 10, 2003
Entry type: trustedCertEntry

Owner: CN=Entrust.net Client Certification Authority, OU=(c) 1999 Entrust.net
Limited, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab.,
O=Entrust.net, C=US
Issuer: CN=Entrust.net Client Certification Authority, OU=(c) 1999 Entrust.net
Limited, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab.,
O=Entrust.net, C=US
Serial number: 380391ee
Valid from: Wed Oct 13 04:24:30 KST 1999 until: Sun Oct 13 04:54:30 KST 2019
Certificate fingerprints:
MD5: 0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4
SHA1: DA:79:C1:71:11:50:C2:34:39:AA:2B:0B:0C:62:FD:55:B2:F9:F5:80

... »ý·« ...


´ÙÀ½°ú °°Àº ¹æ¹ýÀ¸·Î Å°½ºÅä¾î ÆÄÀÏ¿¡ Trusted CA ÀÎÁõ¼­¸¦ Ãß°¡·Î µî·ÏÇÒ ¼ö ÀÖ´Ù. CA ÀÎÁõ¼­´Â À¥ºê¶ó¿ìÀú¿¡¼­ ¿­¼è¸ð¾çÀÇ ¾ÆÀÌÄÜÀ» ´©¸£¸é ÇØ´ç ½ÎÀÌÆ® ÀÎÁõ¼­¸¦ º¼ ¼ö ÀÖ°í, °Å±â¿¡¼­ ÀÎÁõ¼­¸¦ º¹»çÇÒ ¼ö ÀÖ´Ù. ¾Æ·¡ ¿¹½Ã´Â Trusted CA ÀÎÁõ¼­¸¦ ${JAVA_HOME}\jre\lib\secutiry\cacerts¿¡ µî·ÏÀ» ÇÏ´Â ¹æ¹ýÀÌ´Ù.

C:\j2sdk1.4.2\jre\lib\security>keytool -import -keystore cacerts -file 
c:\certs\TradeSignCA.cer -alias tradesignca
Enter keystore password:  changeit
Owner: CN=TradeSignCA, OU=AccreditedCA, O=TradeSign, C=KR
Issuer: CN=KISA RootCA 1, OU=Korea Certification Authority Central, O=KISA, C=KR
Serial number: 2764
Valid from: Tue Nov 15 11:14:59 KST 2005 until: Sun Nov 15 11:14:59 KST 2015
Certificate fingerprints:
         MD5:  C2:E0:27:3D:36:4B:86:29:74:4D:6B:9F:5A:B5:01:26
         SHA1: A0:CD:6A:6D:A4:7B:73:15:F5:8A:CB:1F:C6:FD:C2:14:C9:3B:5D:BE
Trust this certificate? [no]:  y
Certificate was added to keystore


ÀÌ·¸°Ô ¼­¹ö CA ÀÎÁõ¼­°¡ ½Å·ÚÇÏ´Â ÀÎÁõ¼­·Î µî·ÏÀÌ µÇ¸é, ÀÏ¹Ý HTTP Åë½Å°ú °°ÀÌ URLÀÌ https://ÀÎ ÁÖ¼Ò·Î SSL Åë½ÅÀ» Á¤»óÀûÀ¸·Î ÇÒ ¼ö ÀÖ´Ù. Å°½ºÅä¾î ÆÄÀÏ¿¡¼­ ÀÎÁõ¼­¸¦ Á¦°ÅÇÏ´Â ¹æ¹ýÀº ¾Æ·¡¿Í °°´Ù.

C:\jdk1.4.2\jre\lib\security>keytool -delete -keystore cacerts -alias tradesignca
Enter keystore password:  changeit


¾Æ·¡Ã³·³ ¼­¹ö ½ÎÀÌÆ® ÀÎÁõ¼­¸¦ ¹Ù·Î µî·ÏÇÒ ¼öµµ ÀÖ´Ù. ±×·¯³ª ½ÎÀÌÆ® ÀÎÁõ¼­´Â º¸Åë Trusted CA ÀÎÁõ¼­º¸´Ù À¯È¿±â°£ÀÌ Âª¾Æ ¸Å¹ø °»½ÅÀ» ÇØÁà¾ß ÇÒ °ÍÀÌ´Ù.

C:\jdk1.4.2\jre\lib\security>keytool -import -keystore cacerts -file
c:\certs\www.java2go.net.cer -alias mykey
Enter keystore password:  changeit
Owner: CN=www.java2go.net, OU=KTNET, OU=AccreditedCA, O=TradeSign, C=KR
Issuer: CN=TradeSignCA, OU=AccreditedCA, O=TradeSign, C=KR
Serial number: 596e9cf0
Valid from: Tue May 12 13:37:20 KST 2009 until: Wed May 12 14:07:20 KST 2010
Certificate fingerprints:
         MD5:  EF:EB:11:66:BD:CC:B1:D4:88:35:AB:25:9F:2F:79:8B
         SHA1: DC:C4:31:20:46:25:72:68:8B:96:AC:92:EE:F3:8D:15:EF:A7:46:2D
Trust this certificate? [no]:  y
Certificate was added to keystore


3. Commons HttpClientÀÇ SSL Ä¿½ºÅ͸¶ÀÌ¡
±âº»ÀûÀÎ »ç¿ë¹ý ÀÌ¿Ü¿¡ Àڱ⼭¸í(self-signed)µÇ¾ú°Å³ª ¶Ç´Â ½Å·ÚµÇÁö ¾ÊÀº(untrusted) SSL ÀÎÁõ¼­¸¦ »ç¿ëÇÏ´Â °æ¿ìó·³ SSL Åë½ÅÀ» Ä¿½ºÅ͸¶ÀÌ¡ÇÒ ÇÊ¿ä°¡ ÀÖÀ» ¼ö ÀÖ´Ù. 

±âº» Ä¿½ºÅ͸¶ÀÌ¡ ¹æ¹ýÀº org.apache.commons.httpclient.protocol.SecureProtocolSocketFactoryÀ» ±¸ÇöÇؼ­ org.apache.commons.httpclient.protocol.Protocol¸¦ »ý¼ºÇÏ¿© µî·ÏÇØÁÖ¸é µÈ´Ù. ´ÙÀ½°ú °°Àº ÄÚµå ÇÑ ÁÙÀ» Ãß°¡ÇØ ÁÖ¸é µÈ´Ù. ÀÚ¼¼ÇÑ ³»¿ëÀº ÀÌ°÷À» ÂüÁ¶ÇÑ´Ù.

Protocol.registerProtocol("https", 
new Protocol("https", new MySSLSocketFactory(), 443));


Commons HttpClientÀÇ contribution ÆÐÅ°Áö¿¡¼­ »ç¿ëÇÒ ¼ö Àִ EasySSLProtocolSocketFactory¸¦ »ç¿ëÇÏ¸é ½Å·ÚµÇÁö ¾ÊÀº Àڱ⼭¸í(self-signed)µÈ ÀÎÁõ¼­¸¦ °¡Áø ¼­¹ö¿Íµµ ¹Ù·Î SSL Åë½ÅÀ» ÇÒ ¼ö ÀÖ´Ù. Áï, cacerts Å°½ºÅä¾î¿¡ ¼­¹ö ÀÎÁõ¼­¸¦ º°µµ·Î µî·ÏÇÒ ÇÊ¿ä°¡ ¾ø´Ù. ´ÙÀ½°ú °°ÀÌ »ç¿ëÇÒ ¼ö ÀÖ´Ù.

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.protocol.Protocol;

public class HttpClientSample2 {

    public static void main(String[] args) {

        HttpClient httpclient = new HttpClient();
        GetMethod httpget = new GetMethod("https://www.java2go.net/");

        try {
            Protocol.registerProtocol("https", new Protocol("https",
                    new EasySSLProtocolSocketFactory(), 443));

            int statusCode = httpclient.executeMethod(httpget);

            System.out.println("Response Status Code: " + statusCode);
            System.out.println("Response Status Line: " + httpget.getStatusLine());
            System.out.println("Response Body: \n"
                    + httpget.getResponseBodyAsString());

            if (statusCode == HttpStatus.SC_OK) {
                System.out.println("Success!");
            } else {
                System.out.println("Fail!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpget.releaseConnection();
        }
    }
}


È£Ã⠷α×

{DEBUG} [2009-06-18 23:29:31,062] <org.apache.commons.httpclient.HttpConnection> ()
 : Open connection to www.java2go.net:443


ÂüÁ¶: http://hc.apache.org/httpclient-3.x/sslguide.html