Back-End/그 외

[Android] 사설 SSL 인증서를 이용한 https 통신

HMHA 2023. 2. 9. 13:38
300x250
반응형

과정은 인증서를 설정해주는 것 외에는 보통의 hHttpURLConnection을 이요한 통신과 흡사하다.

 

private HttpsURLConnection urlConnection;
    private String method;
    private SSLContext sslContext;

    public static int BUFFER_SIZE = 1024;

    public HttpsURLConnection getConnection(Context context, String url, String requestMethod) {
        try {
            setCertification(context);

            // URL 설정
            URL request_url = new URL(url);
            method = requestMethod;

            urlConnection = (HttpsURLConnection) request_url.openConnection();
            urlConnection.setRequestMethod(method);
            urlConnection.setReadTimeout(95 * 1000);
            urlConnection.setConnectTimeout(95 * 1000);
            urlConnection.setDoInput(true);

            if (requestMethod.equals("GET"))
            {
                urlConnection.setRequestProperty("Accept", "application/json");
                urlConnection.setRequestProperty("X-Environment", "android");
            } else {
                urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
                urlConnection.setRequestProperty("X-Environment", "android");
            }

            urlConnection.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            // 위에서 설정한 인증서 사용
            urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());

            urlConnection.connect();

        } catch(ConnectException ce) {
            // 커넥션 오류
            ce.printStackTrace();
            return null;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return urlConnection;
    }

주의점은 HttpURLConnection이 아닌 HttpsURLConnection이다. 's'가 붙어있다.

 

메소드는 HttpURLConnection을 상속하고 있어서 비슷하다.

    private void setCertification(Context context) throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        InputStream caInput = context.getResources().openRawResource(R.raw.nive_crt);
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
            System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }

        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
    }

코드 원본 : https://developer.android.com/training/articles/security-ssl?hl=ko

 

구글 문서에서 제공하는 코드이다. 인증서 데이터는 /res/raw/ 에 두고 openRawResource()메소드로 가져오고 있다.

 

    public String request(String content) {
        try {
            if(method.equals("POST")) {
                // POST 일때만 실행
                OutputStream outputStream = urlConnection.getOutputStream();
                BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
                bufferedWriter.write(content);
                bufferedWriter.flush();
                bufferedWriter.close();
                outputStream.close();
            }

            String response = null;
            if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                response = readStream();
            }

            urlConnection.disconnect();

            return response;
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    private String readStream() throws Exception {
        StringBuilder responseStringBuilder = new StringBuilder();

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
        for (; ; ) {
            String stringLine = bufferedReader.readLine();
            if (stringLine == null) break;
            responseStringBuilder.append(stringLine + '\n');
        }
        bufferedReader.close();

        return responseStringBuilder.toString();
    }

    public void disconnect() {
        urlConnection.disconnect();
    }

 

출처 : https://nobilitycat.tistory.com/entry/Android-%EC%82%AC%EC%84%A4-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-https-%ED%86%B5%EC%8B%A0

 

[Android] 사설 SSL 인증서를 이용한 https 통신

과정은 인증서를 설정해주는 것 외에는 보통의 hHttpURLConnection을 이요한 통신과 흡사하다. private HttpsURLConnection urlConnection; private String method; private SSLContext sslContext; public static int BUFFER_SIZE = 1024; pub

nobilitycat.tistory.com

 

300x250
반응형