반응형
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 |