본문 바로가기
킷도우의 IT/스프링(Spring)

[실무 경험담] 스프링 HTTP 통신 방법(Spring Http URL Connection, SHA 256 암호화, SSL 인증 우회 방법)

by 킷도우 2022. 12. 22.
반응형

안녕하세요. IT Window 킷도우입니다.

오늘 정말 눈이 펑펑 내리는 하루였는데요. 낮에는 바닥에 눈이 많이 녹으면서 걸어다니기도 꽤 힘든 하루였던 것 같습니다. 내일은 역대급 강 추위라고 하니 대비 잘 하셔야겠습니다. 

 

오늘 여러분들에게 설명드릴 글을 바로!

스프링 HTTP 통신 방법입니다. 제가 전 직장에서 모 PG사와 API 통신을 통해 인터페이스 해야하는 개발 건이 들어왔었는데요. HTTP 통신과 더불어 중요 KEY 정보를 SHA 256으로 암호화하고 또 SSL 인증 오류를 우회하는 방법으로 처리한 것까지 한 번에 살펴 보도록 하겠습니다. 그럼 바로 본론으로 들어가겠습니다.

 

1. ServiceImpl.java에 작성한 전체 소스

개발 순서는 이렇습니다.

1) API 통신을 위해 필요한 파라미터 값 중 중요 정보를 SHA 256으로 암호화 해주기

2) API 통신을 위해 필요한 파라미터 값들을 JSONOBJECT에 담고 형 변환하여 String으로 전환하기

3) HTTPS 통신해야 하는 경우 사전에 SSL 인증 우회 소스 추가하기

4) HTTP Request 보내기

5) HTTP Response 받기

6) HTTP Connection 종료

 

위 순서대로 아래 소스에 주석을 달아 설명을 드릴테니 스텝별로 잘 따라와 주세요. 그리고 당연히 Spring에서 비즈니스 로직을 작성하는 영역은 ServiceImpl.java입니다. Controller.java에 로직을 작성 한다면 기능이야 동작하겠지만.. 스프링을 쓰는 이유는 유지보수 성을 높이기 위함이니 rule에 따라 개발하면 되겠습니다.

@Override
public Map<String, Object> sendSmsReqToPG(Map<String, Object> ds_smsReqHeader, Map<String, Object> ds_smsReqBody) throws Exception{
    //필자는 이미 Front화면에서 PG사로 전송할 파라미터 값들을 Map형태로
    //ds_smsReqHeader, ds_smsReqBody라는 Map 객체에 전부 담아 스프링에서 전달 받은 상황이라
    //별도 파라미터 값을 세팅하는 부분은 생략됐습니다.
    
    // 1) SHA 256 암호화
    SHA256 sha256 = new SHA256();
    // 아래는 양사간 인증을 위한 key값을 만드는 과정입니다.
    String Key = ds_smsReqHeader.get("ID1").toString() + ds_smsReqBody.get("ID2") + ds_smsReqHeader.get("trDtm").toString() + "서로 약속한 통신 key값";
    String encKey = sha256.encrypt(Key);
    ds_smsReqBody.put("encKey", encKey);

    // 2) JSON형태의 STRING으로 변환
    JSONObject jsonHeader =  new JSONObject(ds_smsReqHeader);
    JSONObject jsonBody =  new JSONObject(ds_smsReqBody);
    JSONObject jsonInput = new JSONObject();
    jsonInput.put("body", jsonBody);
    jsonInput.put("header", jsonHeader);
    String jsonInputString = jsonInput.toString();
    System.out.println("보낼 JSON STRING : " + jsonInputString);

    // 3) SSL 인증 우회하기(아래 추가 소스를 참조하세요)
    disableSslVerification();
    
    // 4) Request To PG사
    URL url = new URL ("https://PG사/smslink/api");
    HttpURLConnection con = (HttpURLConnection)url.openConnection();
    con.setRequestMethod("POST");
    con.setRequestProperty("Content-Type", "application/json; utf-8");
    con.setRequestProperty("Accept", "application/json");
    con.setDoOutput(true);
    try(OutputStream os = con.getOutputStream()){
        byte[] input = jsonInputString.getBytes("utf-8");
        os.write(input,0,input.length);
    }

    // 5) Recieve Result From PG사
    String resString = "";
    try(BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(),"utf-8"))){
        StringBuilder response = new StringBuilder();
        String responseLine = null;
        while((responseLine = br.readLine())!=null){
            response.append(responseLine.trim());
        }
        resString = response.toString();
    } 
    // 6) HTTP Connection 종료, 세션 종료
    con.disconnect();
	
    // 이후 결과값을 가공하는 것은 상황에 맞게 해주시면 됩니다.
    ObjectMapper mapper = new ObjectMapper();
    Map<String, Object> ds_smsRespHeader = mapper.readValue(resString, Map.class);
    return ds_smsRespHeader;
}

 

2. SSL 인증 우회 소스

 SSL 인증 우회를 하지 않을 경우 아래와 같은 에러가 발생할텐데요.

SSL 인증 실패로 인한 Handshake 오류

 SSL 인증 우회 소스는 어느 경우에 필요할까요? 요청하는 URL이 HTTP인 경우에는 별도로 SSL 인증 우회가 필요하지 않습니다. HTTPS 주소로 요청할 경우 필요합니다. HTTPS는 보통 웹 사이트 상에서 로그인이나 결제 등을 진행할 때(즉 클라이언트 PC와 서버 PC간 중요한 고객 정보를 서로 주고 받을 때) HTTPS 통신을 진행하게 되는데요. 이 HTTP 통신간에 SSL 암호화를 하여 각종 보안 사고를 방지하기 위함이죠.

 사용자들에게 노출된 웹 사이트의 경우는 그렇고, 그럼 회사와 회사간 API통신을 하는 경우는 어떨까요? 위에서 보이는 것처럼 SHA256을 통해 중요 정보를 암호화 하기도 했고, 또 서로 통신을 위해 양사간 특정 IP만 방화벽을 뚫었을 것이므로 상대적으로 안전한? 검증된 환경에서 통신하는 것으로 간주할 수 있겠습니다. 물론 SSL 인증을 하면 더 좋겠지만 이렇게 될 경우 양 서버간 인프라 작업이 더 복잡해질 것 같네요 ㄷㄷ;

 그래서 인증 우회 소스로 많이들 개발 하시는데 사실 아래 소스를 하나하나 정확히 이해하는 것은 어렵고 아 이렇게하면 SSL 인증 우회되는구나~ 정도로 이해해주시고 넘어가셔도 될 것 같습니다.

private static void disableSslVerification(){
    try{
        /* SSL 인증 우회 처리 시작 */
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }

            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        } };
        
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
  
        HostnameVerifier allHostsValid = new HostnameVerifier(){
            public boolean verify(String hostname, SSLSession session){
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        /* SSL 인증 우회 처리 종료*/
    }catch(NoSuchAlgorithmException e){
        e.printStackTrace();
    }catch(KeyManagementException e){
        e.printStackTrace();
    }

}

 

네 이상으로 스프링 HTTP 통신 방법과 더불어 중요 KEY 정보를 SHA 256으로 암호화하고 또 SSL 인증을 우회하는 방법을 살펴봤습니다. 작은 도움되길 바라면서 이만 글을 마치겠습니다. 

 

감사합니다!

반응형

댓글