java
HTTPS 통신
tmxhsk99
2019. 5. 2. 14:51
인증 처리를 무시한체 접속하는 HTTPS 통신
package com.test.https.practice;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
//인증 없이 서버접속
public class HttpsClientWithoutValidation {
public void getHttps(String urlString) throws IOException, NoSuchAlgorithmException, KeyManagementException{
//get Https urlconnection
URL url = new URL(urlString);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//호스트 이름 검증 설정
conn.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
//무시한다 호스트네임 검증을 항상 트루를 반환
return true;
}
});
//SSL셋팅
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
conn.setSSLSocketFactory(context.getSocketFactory());
//Connect to host
conn.connect();
conn.setInstanceFollowRedirects(true);
//Print response from host
InputStream in = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line =null;
while((line = br.readLine())!= null){
System.out.printf("%s\n",line);
}
br.close();
}
public static void main(String[] args) throws KeyManagementException, NoSuchAlgorithmException, IOException {
HttpsClientWithoutValidation test = new HttpsClientWithoutValidation();
test.getHttps("https://www.google.com");
}
}
공인인증된 인증서로 서버인증
SSLContext.init() 함수의 두번째 인자에 X509TrustManager 를 선언하여 집어 넣었다.
그리고 JRE 를 설치하면 기본적으로 [JRE 경로]/lib/security/cacerts 라는 파일명의 공인 인증된 인증서 저장소 파일이 있다.
해당 인증서 저장소를 이용하여 서버의 인증서를 검사하게 하였다.
package com.test.https.practice;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
//공인 인증된 인증서로 서버 인증
public class HttpsClientWithDefaultCACert {
public void getHttps(String urlString) throws IOException, NoSuchAlgorithmException, KeyManagementException{
//get https URL connection
URL url = new URL(urlString);
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
//호스트 이름 검증 설정
conn.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
//호스트 이름 검증을 무신한다. 항상 트루를 반환
return true;
}
});
//SSL settig
SSLContext context = SSLContext.getInstance("TLS");
context.init(null,new TrustManager[] {new X509TrustManager(){
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//클라이언트 인증 체크
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//서버 인증 체크
try {
//get trust store
KeyStore trustStore = KeyStore.getInstance("JKS");
String cacertPath = System.getProperty("java.home")+"/lib/security/cacerts";
//Trust store path should be diffrent by system plaform.
trustStore.load(new FileInputStream(cacertPath), "changeit".toCharArray());
//Use Default certification validation
//get Trust Manager
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
TrustManager[] tms = tmf.getTrustManagers();
((X509TrustManager)tms[0]).checkServerTrusted(chain, authType);
} catch (KeyStoreException e) {
e.printStackTrace();
}catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} }, null);
//Connect to host
conn.connect();
conn.setInstanceFollowRedirects(true);
//Prinst response from host
InputStream in = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = null;
while((line = br.readLine()) != null){
System.out.printf("%s\n",line);
}
br.close();
}
public static void main(String[] args) throws KeyManagementException, NoSuchAlgorithmException, IOException {
HttpsClientWithDefaultCACert test = new HttpsClientWithDefaultCACert();
test.getHttps("https://www.google.com");
}
}
서버는 지정된 인증키 저장소를 이용해 클라이언트에 자신을 인증하는 키를 보내게 됨.
인증과정이 성공하면 클라이언트에게 html 내용물을 전달하고 종료
package com.test.https.practice;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
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 javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.swing.KeyStroke;
//사용자가 만든 인증키를 이용하는 간단한 HTTPS 서버
//keystore.jks - 서버(SimpleHttpsServer) 에서 사용하는 인증키 저장소
//ruststore.jks - 클라이언트(HttpsClientWithCustomCert) 에서 서버 인증시 사용하는 인증서 저장소
public class SimpleHttpsServer {
public void run(int port) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException{
//create ssl context
SSLContext context = SSLContext.getInstance("TLS");
//set keystore
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("keystore.jks"), "jks파일생성시 입력한 패스워드".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, "kjh48001".toCharArray());
context.init(kmf.getKeyManagers(), null, null);
//creat ssl socket
SSLServerSocketFactory factory = context.getServerSocketFactory();
SSLServerSocket socket = (SSLServerSocket)factory.createServerSocket(port);
SSLSocket client = (SSLSocket) socket.accept();
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();
//read from client
BufferedReader br = new BufferedReader(new InputStreamReader(in));
br.readLine();
//write to client
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write("HTTP/1.0 200 OK");
writer.newLine();
writer.write("Content-Type: text/html");
writer.newLine();
writer.newLine();
writer.write("<html><head><title>hello https</title></head><body>Hello HTTPS<body></html>");
writer.flush();
//close
writer.close();
br.close();
client.close();
}
public static void main(String[] args) throws UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException {
SimpleHttpsServer server = new SimpleHttpsServer();
server.run(8080);
}
}
클라이언트는 지정된 인증저장소를 이용해 서버를 인증한다.
인증과정이 성공하면 html내용물을 전달 받는다.
package com.test.https.practice;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
//사용자가 만든 인증서를 이용하여 서버인증
public class HttpsClientWithCustomCert {
public void getHttps(String urlString) throws IOException, NoSuchAlgorithmException, KeyManagementException{
//get Https URL connection
URL url = new URL(urlString);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//Set HostName verification
conn.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
//호스트 이름 검증은 무시 항상 true를 반환
return true;
}
});
//SSL setting
SSLContext context = SSLContext.getInstance("TLS");
context.init(null,new TrustManager [] {
new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//서버 인증 체크
try {
//get turst store
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("truststore.jks"), "jks생성시 입력한 인증서 비밀번호 ".toCharArray());
// getTrust Manager
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
TrustManager[] tms = tmf.getTrustManagers();
((X509TrustManager)tms[0]).checkServerTrusted(chain, authType);
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// 클라이언트 인증 체크
}
}
}, null);
conn.setSSLSocketFactory(context.getSocketFactory());
//Connect to host
conn.connect();
conn.setInstanceFollowRedirects(true);
//Print response from host
InputStream in = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = null;
while((line = br.readLine())!=null){
System.out.printf("%s/n", line);
}
br.close();
}
public static void main(String[] args) throws KeyManagementException, NoSuchAlgorithmException, IOException {
HttpsClientWithCustomCert test = new HttpsClientWithCustomCert();
test.getHttps("https://127.0.0.1:8080");
}
}
인증서 파일 생성방법은 이곳을 참조