Programming/Client

Amazon S3 Pre-signed URL의 만료 시간 검사하기

Jiwoo 2024. 10. 13. 23:22

🤔 문제 상황

amazon s3로 저장된 파일의 Pre-Signed url을 전달받는 상황

해당 url을 통해 파일에 접근 할 수 있으며, 만료 기한이 설정되어 있습니다.

어차피 만료기한이 지나면 접근이 불가하지만, 프론트에서 미리 알아내어 이벤트를 제어하고 싶다면 어떻게 해야 할까요?


💡Pre-Signed URL이란?

사전 서명된 URL(Pre-Signed URL)은 특정 파일에 대해 제한된 시간 동안 접근할 수 있도록 서명된 URL을 의미합니다. 기본적으로 Amazon S3와 같은 클라우드 스토리지에 저장된 파일들은 퍼블릭하게 접근할 수 없고, 인증된 사용자만이 접근할 수 있습니다. 그러나 사전 서명된 URL을 사용하면 특정 파일에 대한 일시적이고 제한된 접근 권한을 비인증 사용자인 client에게 제공할 수 있습니다.


구조
ex) https://your-bucket.s3.amazonaws.com/your-file.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20231012%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20231012T123456Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=abcd1234example5678signature

  1. https://your-bucket.s3.amazonaws.com/your-file.txt
    버킷 이름 및 파일 경로: your-bucket은 Amazon S3 버킷 이름이며, your-file.txt는 그 안에 저장된 파일입니다.
  2. X-Amz-Algorithm=AWS4-HMAC-SHA256
    URL에서 사용하는 서명 알고리즘을 나타냅니다. AWS의 서명 버전 4를 사용한 HMAC-SHA256 알고리즘을 뜻합니다.
  3. X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20231012/us-west-1/s3/aws4_request
    AWS 인증 정보가 포함됩니다. 이 인증 정보에는 액세스 키(AKIAIOSFODNN7EXAMPLE), 요청이 생성된 날짜(20231012), 리전(us-west-1), 서비스(s3), 그리고 AWS4 요청을 나타내는 정보가 포함됩니다.
  4. X-Amz-Date=20231012T123456Z
    이 URL이 생성된 날짜와 시간입니다. 여기서 20231012T123456Z는 2023년 10월 12일, 12시 34분 56초 UTC를 나타냅니다.
  5. X-Amz-Expires=3600
    URL이 만료되기까지 남은 시간을 초 단위로 나타냅니다. 여기서는 3600초(즉, 1시간) 동안 유효합니다.
  6. X-Amz-SignedHeaders=host
    서명에 포함된 헤더를 나타냅니다. 이 예에서는 host 헤더가 서명에 포함됩니다.
  7. X-Amz-Signature=abcd1234example5678signature
    이 URL에 대한 서명입니다. 요청이 위조되지 않았음을 보증하는 암호화된 서명 값입니다.

✅ URL 만료 여부 검사 함수

// 만료 여부를 boolean으로 반환
const isUrlExpired = (url: string) => {
  const urlObj = new URL(url)
  const amzDate = urlObj.searchParams.get('X-Amz-Date')
  const amzExpires = urlObj.searchParams.get('X-Amz-Expires')

  if (!amzDate || !amzExpires) return false

  // 'X-Amz-Date' = YYYYMMDDTHHMMSS 변환 (utc이므로 z 붙이기)
  const startDate = new Date(
    `${amzDate.slice(0, 4)}-${amzDate.slice(4, 6)}-${amzDate.slice(6, 8)}T${amzDate.slice(
      9,
      11,
    )}:${amzDate.slice(11, 13)}:${amzDate.slice(13, 15)}Z`,
  )
  const expiryDate = new Date(startDate.getTime() + Number(amzExpires) * 1000) // 만료 시간 계산

  return expiryDate.getTime() < Date.now() // 현재 시간과 비교
}