Chapter01/Open API

[ NCP SENS ] SMS 2Factor 인증

EmmaDev_v 2025. 5. 22. 22:27

 

2차 인증으로 Google Authenticator를 사용하겠다고해서

QR생성하고 테스트한 내용을 전에 포스팅했는데

NCP SENS API  사용해서 sms로 인증하는 방식을 사용하게되었다

 

 

참고 공식 링크

SMS API

 

 

 

 

ncp에서

엑세스키, 시크릿키, 서비스 ID 를 ncp콘솔에서 발급받고,발신 번호도 등록해야한다

 

 

이런것들은 application.yml에 넣어놓고주입받아서 (@Value) 사용함

 

 

딱히 신경쓸건없고

 

저기 저 시그니처 생성하는게현재 시간(timestamp)이랑 method, url, accesskey, secretkey를 가지고조합해서 만드는것임

 

 

 

 

 

코드 참고하세용

 

public void sendSms(String recipientPhone, String code) throws Exception {
        
        if (isMobilePhone(recipientPhone)) {
            String time = String.valueOf(System.currentTimeMillis());

            String url = "/sms/v2/services/" + serviceId + "/messages";
            String signature = makeSignature("POST", url, time, accessKey, secretKey);

            String content = "[2차인증] 인증번호 [" + code + "]를 입력해주세요.";

            JsonObject body = new JsonObject();
            body.addProperty("type", "SMS");
            body.addProperty("from", senderPhone);
            body.addProperty("content", content);

            JsonArray messages = new JsonArray();
            JsonObject msg = new JsonObject();
            msg.addProperty("to", recipientPhone);
            messages.add(msg);
            body.add("messages", messages);

            RequestBody requestBody = RequestBody.create(
                    body.toString(),
                    MediaType.get("application/json; charset=utf-8")
            );

            Request request = new Request.Builder()
                    .url(sensUrl + url)
                    .post(requestBody)
                    .addHeader("x-ncp-apigw-timestamp", time)
                    .addHeader("x-ncp-iam-access-key", accessKey)
                    .addHeader("x-ncp-apigw-signature-v2", signature)
                    .addHeader("Content-Type", "application/json")
                    .build();

            OkHttpClient client = new OkHttpClient();
            Response response = client.newCall(request).execute();

            if (!response.isSuccessful()) {
                accessLogger.error("SMS 전송 실패 : {}", recipientPhone);
                throw new RuntimeException("SMS 전송 실패 : " + response.body().string());
            } else {
                accessLogger.info("SMS 전송 성공 : {} -> [{}]", senderPhone, recipientPhone);
            }
        }
        else{
            throw new RuntimeException("SMS 전송 실패 : 유효하지 않은 휴대폰 번호 [" + recipientPhone + "]");
        }
    }

    private String makeSignature(String method, String url, String timestamp, String accessKey, String secretKey) throws Exception {
        String message = new StringBuilder()
                .append(method).append(" ").append(url).append("\n")
                .append(timestamp).append("\n")
                .append(accessKey)
                .toString();

        SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(signingKey);

        byte[] rawHmac = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(rawHmac);
    }

    private boolean isMobilePhone(String phoneNumber) {
        String cleaned = phoneNumber.replaceAll("[^0-9]", ""); // 숫자만 추출
        return cleaned.matches("^010[0-9]{7,8}$");
    }

 

[애로

 

이런식으로 잘 옵니당

 

 

반응형