웹 개발

[java] https connection

노루아부지 2019. 12. 30. 16:41

HttpsURLConnection이란?

  • java 소스 내에서 SSL 적용된 사이트에 접근하기 위해 사용
  • 데이터의 타입이나 길이는 거의 제한이 없으며, 주로 미리 길이를 알지 못하는 스트리밍 데이터를 주고받는 데 사용된다.

 

URLConnection 또는 HttpURLConnection을 사용하여 통신을 할 때, HTTPS간 통신을 하면 오류가 발생합니다.

String htmlUrl = "https://test.domain.co.kr";

HttpURLConnection conn  = (HttpURLConnection) new URL(htmlUrl).openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("User-Agent", "Mozilla/5.0");

StringBuffer sb = new StringBuffer();
BufferedReader in = 
	new BufferedReader(
    	new InputStreamReader(conn.getInputStream(), "UTF-8"));
        
String inputLine;

while ((inputLine = in.readLine()) != null) {
	sb.append(inputLine);
}

in.close();

 

위와 같이 HttpURLConnection을 하면 아래와 같은 오류가 발생합니다.

 

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

 

위의 오류는 아래와 같은 상황에 발생할 수 있습니다.

  • 해당 사이트에 SSL 인증서가 신뢰하는 기관 인증서가 없거나 SSL/TLS 암호화 버전이 맞지 않는 경우
  • 연결하려는 서버의 인증서가 신뢰하는 인증기관 인증서 목록(keystore)에 없을 경우 - 사설 인증서일 경우
  • 서버/클라이언트 사이에 사용하려는 TLS 버전이 맞지 않을 때(TLS 1.0만 지원하는 서버에 1.2로 hand shaking 요청 등)
  • TLS 통신에 사용하려는 cipher suite가 오래되거나 지원되지 않음(JDK 1.8 부터는 sha1 지원 안되고 sha256 이상을 사용해야 한다고 함)

Client에도 KeyStore를 만들어서 해결하는 방법이 있지만 모든 Client에 설치하는 것은 힘들 수 있습니다.

그래서 유효하지 않은 SSL 인증서를 사용하는 서버에 접근 가능하도록 HttpURLConnection을 설정해야 합니다.

 

 

해결방법

이 글에서는 아무 작업도 하지 않은 TrustManager를 이용하여 우회하는 방법을 사용합니다.

  • 이 방법을 사용하는 경우 보안 이슈가 있을 수 있고, 앱의 경우 배포 reject도 발생할 수 있으니 조심해야 합니다.

방법은 아래와 같이 함수를 하나 호출해주시면 됩니다.

 

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

static {
  disableSslVerification();
}

private static void disableSslVerification() {
  try
  {
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
      public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
      }
      public void checkClientTrusted(X509Certificate[] certs, String authType) {
      }
      public void checkServerTrusted(X509Certificate[] certs, String authType) {
      }
    }};

    // Install the all-trusting trust manager
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

    // Create all-trusting host name verifier
    HostnameVerifier allHostsValid = new HostnameVerifier() {
      public boolean verify(String hostname, SSLSession session) {
	    return true;
	  }
    };

    // Install the all-trusting host verifier
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
  } catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
  } catch (KeyManagementException e) {
    e.printStackTrace();
  }
}

 

 

 

728x90

'웹 개발' 카테고리의 다른 글

[java] 파일 확장자 구하기  (0) 2020.01.30
파일 업로드 취약점 (webshell upload)  (0) 2020.01.30
java file transfer  (0) 2019.12.27
REST API 호출 예제  (0) 2019.12.23
java에서 logback 사용  (0) 2019.12.16
loading