본문 바로가기
Web Programming

Java SSL 인증 무시하기(PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException)

by 맑은안개 2023. 10. 11.

들어가며

클라이언트에서 서버로 https요청시 ssl 인증을 하는 과정에서 인증 정보가 확인되지 않는 경우 이를 처리할 수 있는 방법이 두 가지가 있다.
웹브라우저는 인터넷망을 통해 신뢰할 수 있는 기관들의 루트 인증서부터 하위 목록까지 모두 가지고 있으나, 브라우저가 아닌 어플리케이션등에서 ssl 인증서가 설치된 서버로 서비스 요청하는 경우 해당 인증서의 cert 파일을 등록해줘야 한다.

이번 블로그에서는 인증 절차를 무시하고 https 요청을 처리하는 방법을 알아본다. 시작하기 앞서 이 방법은 특수한 상황에서만 사용되어야 한다. 가령, 내부망 A서버(클라이언트)에서 B서버(인증서 설치)로 서비스 요청 테스트등을 할 때의 경우를 들수 있다.

RestTemplate 요청 후 에러

Spring RestTemplate을 사용하여 https요청시 다음의 오류가 발생했다.

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://authdev.kuh.ac.kr/auth/v1/token": PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785)

SSL 인증 무시 함수 생성

SSL 인증을 무시하는 한다는 것은 모든 인증서를 믿게다는 의미이다. 이런 행위를 http 처리 라이브러리(e.g. okhttp3, resttemplace) 자체에서 SSLContext를 통해 처리할 수 있으나 해당 라이브러리에 종속적이라는 단점이 있다. 하여, 코어라이브러리만을 사용해서 처리한다.

   private static void ignoreCertificates() {
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }};

        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {

        }

    }
  • 스프링 테스트 코드 작성을 위해 static으로 선언했으므로 무시해도 좋다.

https 호출 코드

    private static String getTokenFromAuthServer() {

        String access_token;

        ignoreCertificates();   // SSL 인증 무시
        RestTemplate restTemplate = new RestTemplate();

        ... 중략 ...

        ResponseEntity<String> response = restTemplate.postForEntity(
            AUTH_TOKEN_BASE_URL + "/auth/v1/token",
            request,
            String.class);

        assertTrue(response.getStatusCode().is2xxSuccessful(), "Failed to get access token");

        return access_token;
    }
반응형