OAuth2등을 위해서 java http 통신상에서 remote server가  https를 사용하는 경우 서버상에 해당 인증서 정보를 등록하지 않으면 아래와 같은 오류가 발생한다.

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
java.lang.NullPointerException

핵심은 브라우져가 아닌 java상에서 호출하기 때문이다.

java는 이를 위해  /jre/lib/security/cacerts 파일에 인증서 정보를 등록해서 사용한다.

cacerts파일은 handling은 %java_home%/bin/keytool 명령어를 통해서 관리한다. 

 

1. 현재 서버에 등록된 인증서 정보 조회
keytool -list -v -keystore java_home/jre/lib/security/cacerts

 

2. 인증서의 keystore정보에서 인증서를 파일로 추출
keytool -exportcert -keystore "keystore파일" -storepass "keystore파일의 비밀번호" -file xxx.cert -alias "alias name"

 

3. 앞에서 추출한 파일정보를 cacerts에 추가한다. (cacerts의 default 비밀번호는 changeit 임)
keytool -importcert -keystore ${JAVA_HOME}/jre/lib/security/cacerts -storepass changeit -file xxx.cert -alias "alias name"

 

인증서정보 추가결과

위와 같이 하면 오류가 없어짐.

 

java.security.KeyStore class에 대한 사용

 

KeyStore 파일에서 로딩하려면 저장된 keystore파일 경로와 비밀번호, 그리고 keystore저장시 지정된 alias이름을 알아야함.
KeyStore의 Instance생성은 KeyStore keystore = KeyStore.getInstance("jks"); 와 같은 형태임.
getInstance파라메터에는 keytype이 들어가야함. default는 "jks" 임.

 

keystore.load(new FileInputStream("keystore 파일 경로"), keystorepasswd);

로딩한 keystore파일정보를 조회

Certificate cf = keystore.getCertificate("alias Name");

위의 certificate정보를 출력해서 정상적으로 로딩되었는지 확인 가능.

 

이렇게 로딩된 keystore파일을 이용해서 ssl 통신에서 사용.

아래의 소스는 unirest lib를 이용한 호출시 적용예

public void setKeyStore() throws Exception {
		
//  ClassPathResource keyResource = new ClassPathResource(keyStorePath);
    FileInputStream fIn = new FileInputStream("/home/user/test.keystore");

    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());		
    keyStore.load(fIn, keyPass.toCharArray());

    //alias 포함여부 확인
    System.out.println("alias exist>>" + keyStore.containsAlias("alias name"));
    //alias를 통한 certificate 정보 조회
    System.out.println("cert info>>" + keyStore.getCertificate("alias name"));
        
    //SSL 통신을 하기 위해 Unirest정보에 cert정보 로딩.
    //여기서 인증서 정보가 cacerts에 등록되지 않으면 오류발생함.
    Unirest.config().clientCertificateStore(keyStore, keyPass);
}

 

 

참고 : www.lesstif.com/system-admin/java-validatorexception-keystore-ssl-tls-import-12451848.html