Portal/Notes πŸ“
Programming

Signed URL

Memahami signed URL β€” URL terautorisasi dengan batas waktu untuk akses aman ke sumber daya tanpa autentikasi langsung.

Versi Bahasa Indonesia. Baca dalam Bahasa Inggris

Signed URL adalah URL terautorisasi dengan batas waktu yang memungkinkan pengguna mengakses sumber daya yang dilindungi (seperti gambar, video, atau dokumen) tanpa mengekspos sistem penyimpanan yang mendasarinya atau memerlukan autentikasi langsung.

URL ini berisi tanda tangan kriptografi dan metadata opsional (seperti waktu kedaluwarsa dan izin akses). Hanya pengguna dengan signed URL yang valid yang dapat mengakses sumber daya.

Cara Kerjanya

  • Seorang pengguna (atau klien) meminta akses ke sumber daya yang dilindungi.
  • Server/layanan membuat signed URL menggunakan private key atau secret.
  • Pengguna dapat mengunggah, mengunduh, atau melihat (dapat dilindungi hanya untuk mengunduh) sumber daya menggunakan URL tersebut hingga kedaluwarsa.
  • Setelah URL kedaluwarsa, akses dicabut.

Penggunaan Umum Signed URL

  • Unggah File Aman: Izinkan klien untuk mengunggah file langsung ke penyimpanan tanpa mengekspos sistem backend.
  • Unduh File Aman: Izinkan pengguna untuk mengunduh sumber daya dengan aman tanpa membuatnya publik.
  • Kontrol Akses: Berikan akses sementara ke sumber daya internal atau rahasia.

Berbagi Objek AWS S3 menggunakan Signed URL

Mari kita coba berbagi gambar menggunakan signed URL di AWS S3.

Di sini kita akan menggunakan localstack, simulator layanan cloud yang bekerja secara lokal di mesin kita untuk mensimulasikan stack AWS S3. Untuk menginstal localstack Anda dapat mengikuti panduan di sini.

Mulai Localstack

Mulai localstack Anda menggunakan opsi LOCALSTACK_S3_SKIP_SIGNATURE_VALIDATION=0 untuk mengaktifkan validasi tanda tangan request S3 pre-signed URL.

➜ LOCALSTACK_S3_SKIP_SIGNATURE_VALIDATION=0 localstack start

     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,<
 /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_|

- LocalStack CLI: 4.2.0
- Profile: default
- App: https://app.localstack.cloud

[13:29:01] starting LocalStack in Docker mode 🐳
───────────────────── LocalStack Runtime Log (press CTRL-C to quit) ─────────────────────

LocalStack version: 4.2.1.dev7
LocalStack build date: 2025-02-28
LocalStack build git hash: 4285fb18c

Ready.

Buat Bucket

Buat bucket dan tambahkan gambar ke bucket.

➜ awslocal s3api create-bucket --bucket my-bucket
{
    "Location": "/my-bucket"
}
➜ awslocal s3api put-object --bucket my-bucket --key image.png --body bc-logo.png
{
    "ETag": "\"0c8c0a48b20dc18c7645de633daf165a\"",
    "ChecksumCRC32": "6+7i7g==",
    "ChecksumType": "FULL_OBJECT",
    "ServerSideEncryption": "AES256"
}

Pre-Sign dengan AWS CLI

Sekarang Anda dapat membuat dan membagikan signed URL untuk gambar Anda menggunakan perintah di bawah ini.

➜ awslocal s3 presign s3://my-bucket/image.png
http://localhost:4566/my-bucket/image.png?AWSAccessKeyId=test&Signature=XsnJh3uvtdcKlmUHQoVcibO9LD4%3D&Expires=1740985783

Buka URL di browser Anda dan seharusnya akan mulai mengunduh gambar. URL akan kedaluwarsa dalam 3600s atau Anda dapat menimpanya dengan menambahkan opsi --expires-in.

Ketika Anda mencoba mengakses URL setelah kedaluwarsa, akan mengembalikan error AccessDenied: Request has expired.

<Error>
  <Code>AccessDenied</Code>
  <Message>Request has expired</Message>
  <RequestId>bf512477-206d-43dc-9bb8-baaee642db8f</RequestId>
  <Expires>2025-03-03T07:37:10.000Z</Expires>
  <ServerTime>2025-03-03T07:38:04.000Z</ServerTime>
  <X-Amz-Expires>300</X-Amz-Expires>
  <HostId>9Gjjt1m+cjU4OPvX9O9/8RuvnG41MRb/18Oux2o5H5MY7ISNTlXN+Dz9IG62/ILVxhAGI0qyPfg=</HostId>
</Error>

Pre-Sign dengan AWS SDK Golang

Sebagian besar waktu Anda tidak akan menggunakan AWS CLI untuk menghasilkan signed URL. Berikut adalah contoh cara membuat signed URL menggunakan AWS SDK yang terhubung ke localstack di Go.

package main

import (
  "context"
  "fmt"
  "log"
  "time"

  "github.com/aws/aws-sdk-go-v2/aws"
  "github.com/aws/aws-sdk-go-v2/credentials"
  "github.com/aws/aws-sdk-go-v2/service/s3"
)

func main() {
  cfg := aws.Config{
    Region:      "ap-southeast-1", // region apa pun akan berfungsi untuk localstack
    Credentials: credentials.NewStaticCredentialsProvider("test", "test", "test"),
  }

  s3client := s3.NewFromConfig(cfg, func(o *s3.Options) {
    o.BaseEndpoint = aws.String("http://localhost:4566")
    o.UsePathStyle = true
  })

  psClient := s3.NewPresignClient(s3client)
  req, err := psClient.PresignGetObject(context.TODO(), &s3.GetObjectInput{
    Bucket: aws.String("my-bucket"),
    Key:    aws.String("image.png"),
  }, s3.WithPresignExpires(5*time.Minute))
  if err != nil {
    log.Fatal(err)
  }

  fmt.Println(req.URL)
}
➜ go run main.go
http://localhost:4566/my-bucket/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=test%2F20250303%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Date=20250303T073210Z&X-Amz-Expires=300&X-Amz-Security-Token=test&X-Amz-SignedHeaders=host&x-id=GetObject&X-Amz-Signature=07782ba9ccc584bc5f85fd6b41c19cf79024626ce96830eaf4c12783d23455dd

Penyedia Cloud Lainnya

Referensi


Edit on GitHub

Last updated on

Signed URL | Faisal Affan