programing

Java HTTPS 클라이언트 증명서 인증

randomtip 2022. 9. 13. 21:49
반응형

Java HTTPS 클라이언트 증명서 인증

입니다.HTTPS/SSL/TLS증명서를 사용할 때 클라이언트가 정확히 무엇을 제시해야 하는지 혼란스럽습니다.

POST를 특정 특특 a a 로 전송하다URL. 그잘 되는데 문제는 해야 HTTPS . 。HTTPS이든) 하기 HTTPclient Java의 Java를 합니다.HTTPS서포트)를 사용하고 있습니다만, 클라이언트 증명서에 의한 인증에 쫓기고 있습니다.이 질문에는 이미 매우 유사한 질문이 있습니다만, 아직 제 코드로 시도하지 않았습니다(곧 그렇게 될 것입니다).Java 클라이언트는 ).PCAP□□□□□□□□★

증명서를 인증할 때 클라이언트가 서버에 무엇을 제시해야 하는지 알고 싶습니다(특히 Java의 경우, 그것이 중요한 경우). ★★★★★★★★★★★★★★★★★★★★?JKS "파일PKCS#12고객증명서나 키 등 무엇이 들어있습니까?그렇다면 어떤 열쇠입니까?모든 종류의 파일, 증명서 종류 등에 대해 상당히 혼란이 있습니다.

내가 처음 와보기 전에 말씀드렸듯이HTTPS/SSL/TLS배경정보도 주시면 감사하겠습니다(에세이일 필요는 없습니다.

드디어 모든 문제를 해결했으니까, 내 질문에 대답할게.다음은 특정 문제를 해결하기 위해 사용한 설정/파일입니다.

클라이언트의 키스토어는 다음을 포함하는 PKCS#12 형식 파일입니다.

  1. 클라이언트의 퍼블릭 증명서(이 예에서는 자기 서명 CA에 의해 서명됨)
  2. 클라이언트의 개인

위해 OpenSSL의 했습니다.pkcs12들어 명령어를

openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "Whatever"

힌트: 버전 0.9.8h가 아닌 최신 OpenSSL을 입수해 주세요.는 PKCS#12 파일을 정상적으로 생성할 수 없는 버그로 인해 문제가 발생할 수 있기 때문입니다.

이 PKCS#12 파일은 서버가 클라이언트에 인증을 명시적으로 요구했을 때 Java 클라이언트가 클라이언트 증명서를 서버에 제시하기 위해 사용합니다.클라이언트 증명서 인증용 프로토콜의 실제 작동 방법에 대한 개요는 TLS에 관한 Wikipedia 문서를 참조하십시오(또한 클라이언트의 개인 키가 필요한 이유도 여기에 설명되어 있습니다).

클라이언트의 신뢰 스토어는 루트 또는 중간 CA 증명서를 포함하는 스트레이트 JKS 형식 파일입니다.이러한 CA 증명서에 의해 통신이 허가되는 엔드포인트가 결정됩니다.이 경우 클라이언트는 트러스트 스토어의 CA 중 하나에 의해 서명된 증명서를 제시하는 서버에 접속할 수 있습니다.

예를 들어 표준 Java keytool을 사용하여 생성할 수 있습니다.

keytool -genkey -dname "cn=CLIENT" -alias truststorekey -keyalg RSA -keystore ./client-truststore.jks -keypass whatever -storepass whatever
keytool -import -keystore ./client-truststore.jks -file myca.crt -alias myca

스토어를 는 SSL로 핸드쉐이크를 합니다.myca.crt.

위의 파일은 클라이언트 전용입니다.서버도 셋업하는 경우 서버에는 자체 키 및 신뢰 스토어 파일이 필요합니다.(Tomcat을 사용하여) Java 클라이언트와 서버 모두에 대해 완전히 동작하는 예를 설정하기 위한 훌륭한 워크스루를 이 사이트에서 찾을 수 있습니다.

문제/비고/팁

  1. 클라이언트 증명서 인증은 서버에 의해서만 실행할 수 있습니다.
  2. (중요!)서버가 클라이언트 증명서(TLS 핸드쉐이크의 일부)를 요구하면 증명서 요구의 일부로 신뢰할 수 있는 CA 목록도 제공됩니다.인증을 위해 제시하고자 하는 클라이언트 증명서가 이러한 CA 중 하나에 의해 서명되지 않은 경우, 전혀 제시되지 않습니다(내 생각에 이것은 이상한 행동이지만, 거기에는 이유가 있을 것입니다).이것이 제 문제의 주된 원인이었습니다.상대방이 제 자기서명 클라이언트 증명서를 받아들이도록 서버를 올바르게 설정하지 않았기 때문입니다.또한 요청으로 클라이언트 증명서를 제대로 제공하지 못한 것이 문제인 것으로 생각됩니다.
  3. 와이어샤크SSL/HTTPS 패킷 분석 기능이 뛰어나 문제 디버깅 및 검출에 큰 도움이 됩니다.와와니다 it it to -Djavax.net.debug=sslJava SSL 디버깅 출력에 불편함이 있는 경우 보다 구조화되어 해석하기 쉬워집니다.
  4. Apache httpclient 라이브러리를 사용하는 것은 완벽하게 가능합니다.httpclient 를 사용하는 경우는, 행선지 URL 를 HTTPS 에 상당하는 것으로 치환하고, 다음의 JVM 인수를 추가합니다(HTTP/HTTPS 를 개입시켜 데이터를 송수신 하기 위해서 사용하는 라이브러리와는 무관합니다).

    -Djavax.net.debug=ssl
    -Djavax.net.ssl.keyStoreType=pkcs12
    -Djavax.net.ssl.keyStore=client.p12
    -Djavax.net.ssl.keyStorePassword=whatever
    -Djavax.net.ssl.trustStoreType=jks
    -Djavax.net.ssl.trustStore=client-truststore.jks
    -Djavax.net.ssl.trustStorePassword=whatever

그 외의 회답에서는, 클라이언트 증명서를 글로벌하게 설정하는 방법을 나타냅니다.단, JVM 상에서 실행되고 있는 모든 어플리케이션에서 클라이언트키를 글로벌하게 정의하는 것이 아니라, 특정 접속의 클라이언트키를 프로그래밍 방식으로 정의하는 경우는, 다음과 같이 독자적인 SSLContext 를 설정할 수 있습니다.

String keyPassphrase = "";

KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("cert-key-pair.pfx"), keyPassphrase.toCharArray());

SSLContext sslContext = SSLContexts.custom()
        .loadKeyMaterial(keyStore, null)
        .build();

HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpResponse response = httpClient.execute(new HttpGet("https://example.com"));

JKS 파일은 인증서와 키 쌍을 위한 컨테이너일 뿐입니다.클라이언트측 인증 시나리오에서는 키의 다양한 부분이 다음과 같이 배치됩니다.

  • 클라이언트의 스토어에는 클라이언트의 개인 키와 공개 키 쌍이 포함됩니다.이것은 키스토어라고 불립니다.
  • 서버의 스토어에는 클라이언트의 공용 키가 포함됩니다.이것은 트러스트 스토어라고 불립니다.

신뢰 스토어와 키 스토어의 분리는 필수는 아니지만 권장됩니다.동일한 물리적 파일일 수 있습니다.

두 저장소의 파일 시스템 위치를 설정하려면 다음 시스템 속성을 사용합니다.

-Djavax.net.ssl.keyStore=clientsidestore.jks

및 서버:

-Djavax.net.ssl.trustStore=serversidestore.jks

클라이언트의 인증서(공개 키)를 파일로 내보내 서버에 복사하려면

keytool -export -alias MYKEY -file publicclientkey.cer -store clientsidestore.jks

클라이언트의 공개 키를 서버의 키스토어에 Import 하려면 (포스터에 기재된 바와 같이 서버 관리자가 이미 이 작업을 수행했습니다)를 사용합니다.

keytool -import -file publicclientkey.cer -store serversidestore.jks

Maven pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>some.examples</groupId>
    <artifactId>sslcliauth</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>sslcliauth</name>
    <dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.4</version>
        </dependency>
    </dependencies>
</project>

자바 코드:

package some.examples;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.http.entity.InputStreamEntity;

public class SSLCliAuthExample {

private static final Logger LOG = Logger.getLogger(SSLCliAuthExample.class.getName());

private static final String CA_KEYSTORE_TYPE = KeyStore.getDefaultType(); //"JKS";
private static final String CA_KEYSTORE_PATH = "./cacert.jks";
private static final String CA_KEYSTORE_PASS = "changeit";

private static final String CLIENT_KEYSTORE_TYPE = "PKCS12";
private static final String CLIENT_KEYSTORE_PATH = "./client.p12";
private static final String CLIENT_KEYSTORE_PASS = "changeit";

public static void main(String[] args) throws Exception {
    requestTimestamp();
}

public final static void requestTimestamp() throws Exception {
    SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(
            createSslCustomContext(),
            new String[]{"TLSv1"}, // Allow TLSv1 protocol only
            null,
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());
    try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(csf).build()) {
        HttpPost req = new HttpPost("https://changeit.com/changeit");
        req.setConfig(configureRequest());
        HttpEntity ent = new InputStreamEntity(new FileInputStream("./bytes.bin"));
        req.setEntity(ent);
        try (CloseableHttpResponse response = httpclient.execute(req)) {
            HttpEntity entity = response.getEntity();
            LOG.log(Level.INFO, "*** Reponse status: {0}", response.getStatusLine());
            EntityUtils.consume(entity);
            LOG.log(Level.INFO, "*** Response entity: {0}", entity.toString());
        }
    }
}

public static RequestConfig configureRequest() {
    HttpHost proxy = new HttpHost("changeit.local", 8080, "http");
    RequestConfig config = RequestConfig.custom()
            .setProxy(proxy)
            .build();
    return config;
}

public static SSLContext createSslCustomContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {
    // Trusted CA keystore
    KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
    tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());

    // Client keystore
    KeyStore cks = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE);
    cks.load(new FileInputStream(CLIENT_KEYSTORE_PATH), CLIENT_KEYSTORE_PASS.toCharArray());

    SSLContext sslcontext = SSLContexts.custom()
            //.loadTrustMaterial(tks, new TrustSelfSignedStrategy()) // use it to customize
            .loadKeyMaterial(cks, CLIENT_KEYSTORE_PASS.toCharArray()) // load client certificate
            .build();
    return sslcontext;
}

}

증명서와 개인키가 모두 포함된 p12 파일(예를 들어 openssl에 의해 생성됨)을 지정하면 다음 코드는 특정 Https에 대해 해당 파일을 사용합니다.URL연결:

    KeyStore keyStore = KeyStore.getInstance("pkcs12");
    keyStore.load(new FileInputStream(keyStorePath), keystorePassword.toCharArray());
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(keyStore, keystorePassword.toCharArray());
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(kmf.getKeyManagers(), null, null);
    SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    connection.setSSLSocketFactory(sslSocketFactory);

SSLContext초기화에 시간이 걸리기 때문에 캐시하는 것이 좋습니다.

단순히 쌍방향 인증(서버 증명서와 클라이언트 증명서)을 셋업하고 싶은 경우는, 다음의 2개의 링크를 조합하는 것으로 액세스 할 수 있습니다.

양방향 인증 설정:

https://linuxconfig.org/apache-web-server-ssl-authentication

고객이 언급하는 openssl 구성 파일을 사용할 필요는 없습니다.그냥

  • $openssl genrsa -des3 -out ca.key 4096

  • $ openssl req - new - x509 - days 365 - key ca . key - out ca . crt

사용자 자신의 CA 증명서를 생성하고 다음으로 서버 및 클라이언트키를 생성 및 서명합니다.

  • $openssl genrsa -des3 -out 서버.키 4096

  • $ openssl req - new - key server . key - out server . html

  • $ openssl x509 - req - days 365 - in server . csr - CA CA . crt - CA key ca . key - set _ serial 100 - out server . crt

그리고.

  • $openssl genrsa -des3 -out 클라이언트.키 4096

  • $ openssl req - new - key client . key - out client . $ $ $

  • $ openssl x509 - req - days 365 - in client . csr - CA CA . crt - CA key ca . key - set _ serial 101 - out client . crt

그 외의 경우는, 링크의 순서에 따릅니다.Chrome의 증명서 관리는 앞에서 설명한 Firefox의 예와 동일하게 동작합니다.

다음에, 다음의 방법으로 서버를 셋업 합니다.

https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-certificate-on-apache-for-ubuntu-14-04

서버 .crt 및 .key는 이미 작성되었으므로 이 단계를 수행할 필요가 없습니다.

수동으로 https://url로 이동하여 어떤 브라우저에서 어떤 버튼을 클릭하는지, "증명서" 파일을 어디에 어떻게 저장하는지, 마지막으로 키툴이 로컬로 설치하는 마법 주문을 알아내는 것보다 더 좋은 방법이 있습니다.

다음 작업을 수행합니다.

  1. 다음 코드를 InstallCert.java에 저장하십시오.
  2. 명령줄 열기 및 실행:javac InstallCert.java
  3. 실행 방법:java InstallCert <host>[:port] [passphrase](포트 및 패스프레이즈는 옵션)

다음은 Install Cert의 코드입니다.헤더에 있는 연도는 Java의 "나중에" 버전을 위해 일부 부품을 수정해야 합니다.

/*
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.*;
import java.net.URL;

import java.security.*;
import java.security.cert.*;

import javax.net.ssl.*;

public class InstallCert {

    public static void main(String[] args) throws Exception {
  String host;
  int port;
  char[] passphrase;
  if ((args.length == 1) || (args.length == 2)) {
      String[] c = args[0].split(":");
      host = c[0];
      port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
      String p = (args.length == 1) ? "changeit" : args[1];
      passphrase = p.toCharArray();
  } else {
      System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
      return;
  }

  File file = new File("jssecacerts");
  if (file.isFile() == false) {
      char SEP = File.separatorChar;
      File dir = new File(System.getProperty("java.home") + SEP
        + "lib" + SEP + "security");
      file = new File(dir, "jssecacerts");
      if (file.isFile() == false) {
    file = new File(dir, "cacerts");
      }
  }
  System.out.println("Loading KeyStore " + file + "...");
  InputStream in = new FileInputStream(file);
  KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
  ks.load(in, passphrase);
  in.close();

  SSLContext context = SSLContext.getInstance("TLS");
  TrustManagerFactory tmf =
      TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
  tmf.init(ks);
  X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
  SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
  context.init(null, new TrustManager[] {tm}, null);
  SSLSocketFactory factory = context.getSocketFactory();

  System.out.println("Opening connection to " + host + ":" + port + "...");
  SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
  socket.setSoTimeout(10000);
  try {
      System.out.println("Starting SSL handshake...");
      socket.startHandshake();
      socket.close();
      System.out.println();
      System.out.println("No errors, certificate is already trusted");
  } catch (SSLException e) {
      System.out.println();
      e.printStackTrace(System.out);
  }

  X509Certificate[] chain = tm.chain;
  if (chain == null) {
      System.out.println("Could not obtain server certificate chain");
      return;
  }

  BufferedReader reader =
    new BufferedReader(new InputStreamReader(System.in));

  System.out.println();
  System.out.println("Server sent " + chain.length + " certificate(s):");
  System.out.println();
  MessageDigest sha1 = MessageDigest.getInstance("SHA1");
  MessageDigest md5 = MessageDigest.getInstance("MD5");
  for (int i = 0; i < chain.length; i++) {
      X509Certificate cert = chain[i];
      System.out.println
        (" " + (i + 1) + " Subject " + cert.getSubjectDN());
      System.out.println("   Issuer  " + cert.getIssuerDN());
      sha1.update(cert.getEncoded());
      System.out.println("   sha1    " + toHexString(sha1.digest()));
      md5.update(cert.getEncoded());
      System.out.println("   md5     " + toHexString(md5.digest()));
      System.out.println();
  }

  System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
  String line = reader.readLine().trim();
  int k;
  try {
      k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
  } catch (NumberFormatException e) {
      System.out.println("KeyStore not changed");
      return;
  }

  X509Certificate cert = chain[k];
  String alias = host + "-" + (k + 1);
  ks.setCertificateEntry(alias, cert);

  OutputStream out = new FileOutputStream("jssecacerts");
  ks.store(out, passphrase);
  out.close();

  System.out.println();
  System.out.println(cert);
  System.out.println();
  System.out.println
    ("Added certificate to keystore 'jssecacerts' using alias '"
    + alias + "'");
    }

    private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

    private static String toHexString(byte[] bytes) {
  StringBuilder sb = new StringBuilder(bytes.length * 3);
  for (int b : bytes) {
      b &= 0xff;
      sb.append(HEXDIGITS[b >> 4]);
      sb.append(HEXDIGITS[b & 15]);
      sb.append(' ');
  }
  return sb.toString();
    }

    private static class SavingTrustManager implements X509TrustManager {

  private final X509TrustManager tm;
  private X509Certificate[] chain;

  SavingTrustManager(X509TrustManager tm) {
      this.tm = tm;
  }

  public X509Certificate[] getAcceptedIssuers() {
      throw new UnsupportedOperationException();
  }

  public void checkClientTrusted(X509Certificate[] chain, String authType)
    throws CertificateException {
      throw new UnsupportedOperationException();
  }

  public void checkServerTrusted(X509Certificate[] chain, String authType)
    throws CertificateException {
      this.chain = chain;
      tm.checkServerTrusted(chain, authType);
  }
    }

} 

Spring Boot에서 양방향 SSL(클라이언트 및 서버 인증서)을 사용하여 뱅크에 연결했습니다.여기에 나의 모든 스텝을 설명하고, 그것이 도움이 되기를 바랍니다(가장 심플한 솔루션이라고 생각합니다).

  1. 인증서 요청 생성:
  • 개인 키 생성:

         openssl genrsa -des3 -passout pass:MY_PASSWORD -out user.key 2048
    
  • 인증서 요청 생성:

         openssl req -new -key user.key -out user.csr -passin pass:MY_PASSWORD
    

지킨다user.key(및 비밀번호) 및 증명서 요청을 은행으로 전송합니다.

  1. 내 클라이언트 루트 인증서 2개 받기user.pem및 뱅크 루트 증명서:bank.crt

  2. Java keystore를 만듭니다(키 비밀번호를 입력하고 키스토어 비밀번호를 설정합니다).

    openssl pkcs12 -export -in user.pem -inkey user.key -out keystore.p12 -name clientId -CAfile ca.crt -caname root
    

    출력에 신경 쓰지 마십시오.unable to write 'random state'. Java PKCS12keystore.p12창조했다.

  3. 에 " " " "bank.crt(간단하게 하기 위해 1개의 키스토어를 사용했습니다)

    keytool -import -alias bankca -file bank.crt -keystore keystore.p12 -storepass MY_PASS
    

    키 저장소 인증서 확인 방법:

    keytool -list -keystore keystore.p12
    
  4. 코드 Boot Java 를 RestTemplateadd "를 org.apache.httpcomponents.httpcore★★★★★★★★★★★★★★★★★★:

    @Bean("sslRestTemplate")
    public RestTemplate sslRestTemplate() throws Exception {
      char[] storePassword = appProperties.getSslStorePassword().toCharArray();
      URL keyStore = new URL(appProperties.getSslStore());
    
      SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(keyStore, storePassword)
      // use storePassword twice (with key password do not work)!!
            .loadKeyMaterial(keyStore, storePassword, storePassword) 
            .build();
    
      // Solve "Certificate doesn't match any of the subject alternative names"
      SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    
      CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
      HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
      RestTemplate restTemplate = new RestTemplate(factory);
      // restTemplate.setMessageConverters(List.of(new Jaxb2RootElementHttpMessageConverter()));
      return restTemplate;
    }
    

여기서 수정한 것은 키스토어 타입이라고 생각합니다.pkcs12(pfx)는 항상 개인키가 있고 JKS 타입은 개인키 없이 존재할 수 있습니다.코드로 지정하거나 브라우저를 통해 증명서를 선택하지 않는 한 서버는 상대편 클라이언트를 나타내고 있는지 알 수 없습니다.

언급URL : https://stackoverflow.com/questions/1666052/java-https-client-certificate-authentication

반응형