본문 바로가기
Spring/Spring 개발 예제

X-Aiz-Signature-V1란? X-Aiz-Signature-V1 를 이용한 API 통신 보안기능 개발

by 디찌s 2024. 5. 23.
728x90
반응형

 

 

X-Aiz-Signature-V1

 

HTTP 요청 헤더로, 주로 API 통신에서 사용되는 보안 기능을 담당합니다. 이러한 서명 헤더는 데이터의 무결성과 출처의 신뢰성을 확인하기 위해 디지털 서명을 포함하는 경우가 많습니다.

 

주요 용도

  1. 인증 및 인가:
    • 요청을 보낸 사람의 신원을 인증합니다.
    • 전송 중에 요청이 변경되지 않았음을 확인합니다.
  2. 데이터 무결성:
    • 전송된 데이터가 중간에 변경되지 않고, 원본 그대로 도착했음을 보장합니다.
  3. 재전송 방지:
    • 서명에 타임스탬프나 고유 식별자를 포함하여 동일한 요청이 여러 번 전송되는 재전송 공격을 방지합니다.

일반적인 구현 방식

  1. 서명 생성:
    • 요청을 보내는 쪽에서 비밀 키를 사용해 서명을 생성하고, 이를 X-Aiz-Signature-V1 헤더에 포함합니다.
    • 주로 HMAC(해시 기반 메시지 인증 코드) 같은 해시 알고리즘을 사용합니다.
  2. 서명 검증:
    • 요청을 받는 쪽에서 헤더에서 서명을 추출합니다.
    • 수신한 데이터와 비밀 키를 사용해 기대되는 서명을 재계산하고, 헤더의 서명과 비교하여 일치하는지 확인합니다.

예제 시나리오

예를 들어, 클라이언트가 API 요청을 보낼 때, 요청 본문과 타임스탬프를 결합해 HMAC 알고리즘을 사용하여 서명을 생성합니다. 이 서명을 X-Aiz-Signature-V1 헤더에 포함시켜 서버로 보냅니다. 서버는 이 서명을 검증하여 요청이 유효하고 변경되지 않았음을 확인합니다.

이와 같은 서명 헤더는 특히 민감한 데이터를 다루거나, 여러 시스템 간의 안전한 통신이 필요한 환경에서 많이 사용됩니다. 

 

 

예제 코드

서명 생성

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class HMACUtil {

    public static String generateHMAC(String data, String secret) throws Exception {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        byte[] hash = sha256_HMAC.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(hash);
    }
}

 

클라이언트 요청 보내기

Spring의 RestTemplate을 사용하여 서버로 요청을 보내고, X-Aiz-Signature-V1 헤더를 포함합니다.

 

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class ApiClient {

    private static final String SECRET_KEY = "your-secret-key";
    private static final String URL = "http://example.com/api";

    public static void main(String[] args) {
        try {
            // 요청 본문
            String requestBody = "{\"data\":\"Hello, World!\"}";
            String timestamp = String.valueOf(System.currentTimeMillis());
            
            // 서명 생성
            String signatureData = requestBody + timestamp;
            String signature = HMACUtil.generateHMAC(signatureData, SECRET_KEY);

            // 헤더 설정
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "application/json");
            headers.set("X-Aiz-Signature-V1", signature);
            headers.set("X-Timestamp", timestamp);

            // 요청 생성
            HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> response = restTemplate.exchange(URL, HttpMethod.POST, entity, String.class);

            // 응답 출력
            System.out.println("Response: " + response.getBody());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

 

3. 서버에서 서명 검증

서버 측에서는 요청을 수신하고 서명을 검증합니다.

 

import org.springframework.web.bind.annotation.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

@RestController
@RequestMapping("/api")
public class ApiController {

    private static final String SECRET_KEY = "your-secret-key";

    @PostMapping
    public String handleRequest(@RequestBody String body, @RequestHeader("X-Aiz-Signature-V1") String signature, @RequestHeader("X-Timestamp") String timestamp) {
        try {
            // 서명 데이터 생성
            String signatureData = body + timestamp;
            String expectedSignature = HMACUtil.generateHMAC(signatureData, SECRET_KEY);

            // 서명 검증
            if (!expectedSignature.equals(signature)) {
                return "Invalid signature";
            }

            // 요청 처리 로직
            return "Request processed successfully";
        } catch (Exception e) {
            e.printStackTrace();
            return "Error processing request";
        }
    }
}

 

예제 설명

  1. 클라이언트: 요청 본문과 타임스탬프를 결합하여 HMAC-SHA256 서명을 생성하고, 이를 X-Aiz-Signature-V1 헤더에 포함시켜 서버로 전송합니다.
  2. 서버: 요청을 수신한 후, 본문과 타임스탬프를 이용해 서명을 재계산하여 요청의 서명과 비교합니다. 서명이 유효한 경우 요청을 처리하고, 그렇지 않은 경우 오류 메시지를 반환합니다.

이 구현은 기본적인 예제로, 실제 환경에서는 서명 생성 및 검증 로직을 더욱 강화하고, 추가적인 보안 조치를 고려해야 합니다.

728x90
반응형

댓글