1.접속할 사이트에 들어가서 자물쇠를 클릭해 인증서 보기로 모든 체인을 확인해 한 단계씩 모두 인증서를 추출한다.
2.인증서를 병합한다.
copy a.crt + b.crt resultChain.crt
cat a.crt b.crt > resultChain.crt
3.인증서를 등록한다.
keytool -import -alias kifin_chain -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -file resultChain.crt
sudo keytool -import \
-alias kifin_cert \
-keystore "$JAVA_HOME/jre/lib/security/cacerts" \
-file ~/Downloads/resultChain.crt
4.인증서를 잘 들어갔는지 확인한다.
keytool -list -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -alias kifin_cert -storepass changeit
public class SSLClient {
public static void main(String[] args) throws Exception {
// 결과값을 위한 변수들
BufferedReader reader = new BufferedReader();
String line = null;
StringBuffer result = new StringBuffer();
// 1. cacerts 경로와 비밀번호
String cacertsPath = System.getProperty("java.home") + "/lib/security/cacerts";
String cacertsPassword = "changeit";
// 2. Java Key Store 로드
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(cacertsPath);
trustStore.load(instream, cacertsPassword.toCharArray());
instream.close(); // 스트림 닫기
// 3. TrustManagerFactory 생성
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
// 4. SSLContext 생성 및 초기화
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
// 5. SSLSocketFactory 상수, 기본값: SSLSocketFactory. STRICT_HOSTNAME_VERIFIER
SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
// 6. SchemeRegistry 구성
SchemeRegistry sr = new SchemeRegistry();
sr.register(new Scheme("https", 443, sf));
// 7. ConnectionManager 구성
PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(sr);
pccm.setMaxTotal(100); // Connection Pool 최대 사이즈
pccm.setDefaultMaxPerRoute(20); // 각 host(IP와 Port의 조합)당 Connection Pool에 생성가능한 Connection 수
// 8. DefaultHttpClient 생성 및 요청
HttpClient httpClient = new DefaultHttpClient(pccm);
HttpGet httpUrl = new HttpGet("https://yourWebSite?param1=value1");
HttpResponse response = httpClient.execute(httpUrl);
HttpEntity entity = response.getEntity();
// 응답 바디의 값을 꺼내 보여줍니다.
if(entity != null) {
reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
while((line = reader.readLine()) != null) {
result.append(line);
}
reader.close();
}
httpClient.getConnectionManager().shutdown();
// 결과 출력
System.out.println("Result : " + result.toString());
}
}
- TLS 1.2 이상 강제 가능합니다.
- TLS(Transport Layer Security): SSL(Secure Sockets Layer)와 혼동되어 사용되는 용어입니다. SSL은 넷스케이프사에서 1995년에 개발한 HTTP 암호화 프로토콜입니다. 하지만 SSL에는 여러 보안 취약점이 있었기 때문에 사용이 중단되었고, 더 안전한 TLS 프로토콜로 대체되었습니다.
- 최신 버전은 TLS 1.3이며 보안을 위해 TLS 1.2 이상 사용을 권고합니다.
- 커스텀 TrustManager, KeyManager 사용 가능합니다.
- 클라이언트 인증서 설정도 가능합니다.
- 간단한 방식은 SSLContext.getInstance(“TLS”)를 기본적으로 호출합니다.
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
ALLOW_ALL_HOSTNAME_VERIFIER
SSLSocketFactory sf = new SSLSocketFactory(sslContext, SLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
SSLSocketFactory sf = new SSLSocketFactory(sslContext, SLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
- CN : Common Name, 일반이름
- SAN : Subject Alternative Name, 주체 대체 이름
STRICT_HOSTNAME_VERIFIER
SSLSocketFactory sf = new SSLSocketFactory(sslContext, SLSocketFactory.STRICT_HOSTNAME_VERIFIER);
- 가장 엄격한 방식이고, 디폴트 값입니다.
- CN과 정확히 일치해야 하고, SAN을 허용하지 않습니다.
- 스키마 : 프로토콜(ex. http, https)과 해당 프로토콜을 사용하기 위한 소켓 팩토리, 포트 번호 등
ClientConnectionManager ccm = new SingleClientConnManager(sr);
PoolingClientConnectionManager
PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(sr);
String param1 = URLEncoder.encode("한글", "UTF-8");
Reference :