๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๋ณด์•ˆ,์ธ์ฆ,๋„คํŠธ์›Œํฌ ๊ด€๋ จ

SSL ์—ฐ๊ฒฐ ์‹œ ์„œ๋ช…๋œ CA ์ธ์ฆ์„œ๊ฐ€ truststore์— ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ž๋™์œผ๋กœ ๊ฐฑ์‹ ํ•˜๋Š” Java ์ฝ”๋“œ ์˜ˆ์ œ

by beeman 2023. 4. 5.

SSL ์—ฐ๊ฒฐ ์‹œ ์„œ๋ช…๋œ CA ์ธ์ฆ์„œ๊ฐ€ truststore์— ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ž๋™์œผ๋กœ ๊ฐฑ์‹ ํ•˜๋Š” Java ์ฝ”๋“œ ์˜ˆ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

String url = "https://example.com";
HttpClient httpClient = null;
try {
    SSLContext sslContext = SSLContexts.createDefault();
    SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);

    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("https", sslSocketFactory).build();

    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

    httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();

    HttpGet httpGet = new HttpGet(url);
    HttpResponse response = httpClient.execute(httpGet);
    HttpEntity entity = response.getEntity();
    EntityUtils.consume(entity);
} catch (SSLHandshakeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof CertificateException) {
        CertificateException ce = (CertificateException) cause;
        if (ce.getMessage().contains("PKIX path building failed")) {
            X509Certificate[] certs = ((PKIXCertPathBuilderException) ce.getCause()).getCertPath().getCertificates().toArray(new X509Certificate[0]);
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            for (int i = 0; i < certs.length; i++) {
                X509Certificate cert = certs[i];
                keyStore.setCertificateEntry("alias-" + i, cert);
            }
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(keyStore, null).build();
            SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
            httpClient = HttpClients.custom().setSSLSocketFactory(sslSocketFactory).setConnectionManager(connectionManager).build();
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            EntityUtils.consume(entity);
        }
    }
} catch (Exception e) {
    // ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
    throw new RuntimeException("Error initializing HttpClient", e);
}

 

 

์œ„ ์ฝ”๋“œ์—์„œ๋Š” HttpClient๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋„์ค‘ SSLHandshakeException์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ, PKIX path building failed ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ•ด๋‹น ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ์˜ˆ์™ธ์— ํฌํ•จ๋œ CertificateException์—์„œ CA ์ธ์ฆ์„œ๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. ์ดํ›„ KeyStore๋ฅผ ์ƒ์„ฑํ•˜์—ฌ CA ์ธ์ฆ์„œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , TrustManagerFactory๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. TrustManagerFactory์˜ init() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ keyStore๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. SSLContextBuilder๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ SSLContext๋ฅผ ์ƒ์„ฑํ•˜๊ณ , SSLConnectionSocketFactory๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ HttpClient๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์œ„ ์ฝ”๋“œ์—์„œ๋Š” HttpClient์˜ ์ƒ์„ฑ์ด ์‹คํŒจํ•  ๊ฒฝ์šฐ์—๋„ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด try-catch ๋ธ”๋ก์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค.