全部产品
Search
文档中心

Object Storage Service:Tandatangan V4 dalam permintaan PostObject

更新时间:Jul 06, 2025

Untuk memastikan validitas dan keamanan permintaan PostObject, Anda harus menyertakan tanda tangan dalam permintaan tersebut. Tanda tangan V4 dihitung dengan mengenkripsi serangkaian parameter permintaan, termasuk kebijakan dan masa berlaku, menggunakan rahasia AccessKey, waktu saat ini, dan wilayah. Setelah server aplikasi menghasilkan tanda tangan, informasi seperti tanda tangan dan kebijakan unggah dikembalikan ke klien. Klien kemudian menggunakan informasi ini untuk membuat permintaan unggah. OSS akan memverifikasi validitas tanda tangan setelah menerima permintaan unggah. Hanya permintaan dengan tanda tangan yang valid yang diizinkan, sementara permintaan yang gagal verifikasi akan ditolak.

Tanda tangan dalam permintaan PostObject

Untuk meningkatkan keamanan data, permintaan PostObject mengintegrasikan algoritma tanda tangan V4. Elemen formulir dan bidang formulir kebijakan memainkan peran penting dalam memastikan validitas dan keamanan permintaan PostObject.

Elemen formulir

Formulir adalah kumpulan bidang yang terdapat dalam permintaan PostObject untuk mengirimkan informasi tentang objek yang ingin diunggah beserta metadata-nya. Tabel berikut menjelaskan elemen formulir unik dari tanda tangan V4 dalam permintaan PostObject. Untuk informasi lebih lanjut tentang elemen formulir umum, lihat Elemen formulir.

Elemen

Tipe

Diperlukan

Deskripsi

x-oss-signature-version

String

Ya

Versi tanda tangan dan algoritma yang digunakan untuk menghitung tanda tangan. Atur nilainya menjadi OSS4-HMAC-SHA256.

x-oss-credential

String

Ya

Kredensial yang dapat Anda gunakan untuk menghitung tanda tangan. Format:

<AccessKeyId>/<date>/<region>/oss/aliyun_v4_request
  • AccessKeyId: ID AccessKey dari pasangan AccessKey.

  • date: tanggal ketika permintaan dilakukan. Format: YYYYMMDD. Contoh: 20231203.

  • region: ID wilayah Alibaba Cloud tempat bucket yang ingin Anda akses berada. Contoh: cn-hangzhou.

  • oss: nama layanan yang diminta. Atur nilainya menjadi oss.

  • aliyun_v4_request: deskripsi versi tanda tangan dalam permintaan. Atur nilainya menjadi aliyun_v4_request.

x-oss-date

String

Ya

Waktu ketika permintaan dilakukan. Waktu harus mengikuti standar ISO 8601. Contoh: 20231203T121212Z.

  • Offset hingga 15 menit setelah permintaan dilakukan diperbolehkan. Oleh karena itu, waktu ketika server menerima permintaan bisa hingga 15 menit lebih lambat daripada waktu yang ditentukan oleh x-oss-date. Ini memastikan bahwa permintaan dapat diproses sesuai harapan meskipun ada latensi transmisi jaringan atau perbedaan waktu antara klien dan server.

  • Permintaan memiliki periode validitas hingga tujuh hari. Tujuh hari setelah waktu yang ditentukan oleh x-oss-date, OSS akan menolak permintaan dan melaporkan kesalahan. Ini memastikan ketepatan waktu dan keamanan permintaan serta mencegah pengiriman jahat permintaan yang kedaluwarsa atau ditandatangani.

  • Waktu yang ditentukan oleh x-oss-date digunakan sebagai cap waktu untuk string yang ditandatangani. Nilai tersebut harus sama dengan nilai bidang date dalam kunci turunan dan nilai bidang x-oss-date dalam bidang formulir kebijakan.

x-oss-signature

String

Ya

Deskripsi yang digunakan untuk verifikasi tanda tangan. Nilainya dihitung dengan mengenkripsi string kebijakan yang dikodekan Base64 menggunakan HMAC-SHA256, lalu mengonversi hash biner yang diperoleh menggunakan HMAC-SHA256 ke format heksadesimal.

policy

Bidang formulir policy dalam permintaan PostObject digunakan untuk menentukan waktu kedaluwarsa dan kondisi permintaan PostObject yang diinisiasi untuk mengunggah objek menggunakan formulir HTML. Nilai dari bidang formulir policy adalah string JSON yang membatasi permintaan PostObject dengan menentukan beberapa parameter, seperti nama bucket tempat objek akan diunggah, awalan dalam nama objek, periode validitas permintaan, metode HTTP yang diizinkan, serta ukuran dan konten objek.

Penting

Bidang formulir policy harus mencakup parameter expiration dan conditions. Parameter x-oss-security-token hanya diperlukan jika Anda menggunakan token keamanan untuk membangun tanda tangan dalam permintaan PostObject. Parameter ini tidak diperlukan jika Anda menggunakan pasangan AccessKey untuk membangun tanda tangan.

{
  "expiration": "2023-12-03T13:00:00.000Z",
  "conditions": [
    {"bucket": "examplebucket"},
    {"x-oss-signature-version": "OSS4-HMAC-SHA256"},
    {"x-oss-credential": "AKIDEXAMPLE/20231203/cn-hangzhou/oss/aliyun_v4_request"},
    {"x-oss-security-token": "CAIS******"},
    {"x-oss-date": "20231203T121212Z"},
    ["content-length-range", 1, 10],
    ["eq", "$success_action_status", "201"],
    ["starts-with", "$key", "user/eric/"],
    ["in", "$content-type", ["image/jpg", "image/png"]],
    ["not-in", "$cache-control", ["no-cache"]]
  ]
}

Parameter yang diperlukan dalam bidang formulir policy:

  • expiration

    Parameter expiration menentukan waktu kedaluwarsa permintaan. Waktu harus mengikuti standar ISO 8601 dan dalam GMT. Contohnya, 2023-12-03T13:00:00.000Z menunjukkan bahwa permintaan PostObject harus dikirim sebelum pukul 13:00 pada 3 Desember 2023.

  • conditions

    Parameter conditions adalah daftar yang menentukan nilai valid dari bidang formulir dalam permintaan PostObject.

    Parameter

    Tipe

    Diperlukan

    Deskripsi

    Mode pencocokan

    bucket

    String

    Tidak

    Nama bucket.

    bucket

    x-oss-signature-version

    String

    Ya

    Versi tanda tangan dan algoritma yang digunakan untuk menghitung tanda tangan. Atur nilainya menjadi OSS4-HMAC-SHA256.

    x-oss-signature-version

    x-oss-credential

    String

    Ya

    Kredensial yang dapat Anda gunakan untuk menghitung tanda tangan. Format:

    <AccessKeyId>/<date>/<region>/oss/aliyun_v4_request
    • AccessKeyId: ID AccessKey dari pasangan AccessKey.

    • date: tanggal ketika permintaan dilakukan.

    • region: ID wilayah Alibaba Cloud tempat bucket yang ingin Anda akses berada. Contoh: cn-hangzhou.

    • oss: nama layanan yang diminta. Atur nilainya menjadi oss.

    • aliyun_v4_request: deskripsi versi tanda tangan dalam permintaan. Atur nilainya menjadi aliyun_v4_request.

    x-oss-credential

    x-oss-security-token

    String

    Tidak

    Parameter ini hanya diperlukan ketika Anda menggunakan token keamanan untuk membangun tanda tangan dalam permintaan PostObject. Anda dapat memanggil operasi AssumeRole STS untuk mendapatkan token keamanan.

    x-oss-security-token

    x-oss-date

    String

    Ya

    Waktu ketika permintaan dilakukan. Waktu harus mengikuti standar ISO 8601. Contoh: 20231203T121212Z.

    • Offset hingga 15 menit setelah permintaan dilakukan diperbolehkan. Oleh karena itu, waktu ketika server menerima permintaan bisa hingga 15 menit lebih lambat daripada waktu yang ditentukan oleh x-oss-date. Ini memastikan bahwa permintaan dapat diproses sesuai harapan meskipun ada latensi transmisi jaringan atau perbedaan waktu antara klien dan server.

    • Permintaan memiliki periode validitas hingga tujuh hari. Tujuh hari setelah waktu yang ditentukan oleh x-oss-date, OSS akan menolak permintaan dan melaporkan kesalahan. Ini memastikan ketepatan waktu dan keamanan permintaan serta mencegah pengiriman jahat permintaan yang kedaluwarsa atau ditandatangani.

    • Waktu yang ditentukan oleh x-oss-date digunakan sebagai cap waktu untuk string yang ditandatangani. Nilai tersebut harus sama dengan nilai bidang date dalam kunci turunan dan nilai bidang x-oss-date dalam bidang formulir kebijakan.

    x-oss-date

    content-length-range

    String

    Tidak

    Ukuran minimum dan maksimum objek yang ingin Anda unggah. Unit: byte.

    content-length-range

    success_action_status

    String

    Tidak

    Kode status HTTP yang dikembalikan setelah objek diunggah.

    eq, starts-with, in, dan not-in

    key

    String

    Tidak

    Nama objek yang ingin Anda unggah.

    eq, starts-with, in, dan not-in

    content-type

    String

    Tidak

    Jenis objek yang ingin Anda unggah.

    eq, starts-with, in, dan not-in

    cache-control

    String

    Tidak

    Perilaku caching objek.

    eq, starts-with, in, dan not-in

Mode pencocokan kondisi

Mode pencocokan

Deskripsi

content-length-range

Ukuran objek yang ingin Anda unggah harus berada dalam rentang ukuran objek yang didukung. Sebagai contoh, jika ukuran objek yang didukung adalah 1 hingga 10 byte, kondisinya harus ["content-length-range", 1, 10].

eq

Nilai bidang formulir harus persis sama dengan nilai yang ditentukan dalam kondisi. Sebagai contoh, jika nilai bidang formulir key harus a, Anda dapat menentukan ["eq", "$key", "a"] sebagai kondisi.

starts-with

Nilai bidang formulir harus dimulai dengan awalan tertentu. Sebagai contoh, jika nilai bidang formulir key dimulai dengan user/user1, Anda dapat menentukan ["starts-with", "$key", "user/user1"] sebagai kondisi.

in

Elemen yang ingin Anda sertakan dalam verifikasi. Elemen-elemen tersebut harus ditentukan dalam string kondisi. Sebagai contoh, jika Anda ingin memverifikasi apakah jenis objek yang ingin Anda unggah adalah gambar dan ingin mengizinkan pengunggahan gambar dalam berbagai format dalam permintaan PostObject, kondisinya harus ["in", "$content-type", ["image/jpg", "image/png"]].

not-in

Elemen yang ingin Anda kecualikan dari verifikasi. Elemen-elemen tersebut harus ditentukan dalam string kondisi. Sebagai contoh, jika Anda ingin menentukan perilaku caching objek dan mengecualikan elemen no-cache, kondisinya harus ["not-in", "$cache-control", ["no-cache"]].

Karakter escape untuk bidang formulir policy

Dalam bidang formulir policy permintaan PostObject, tanda dolar ($) menentukan variabel. Untuk mendeskripsikan tanda dolar ($), gunakan karakter escape berikut: \$. Tabel berikut menjelaskan karakter escape yang digunakan dalam string JSON bidang formulir policy dalam permintaan PostObject.

Karakter escape

Deskripsi

\/

Garismiring

\\

Garis miring terbalik

\"

Tanda kutip ganda

\$

Tanda dolar

\b

Ruang kosong

\f

Pemisah formulir

\n

Baris baru

\r

Carriage return

\t

Tab horizontal

\uxxxx

Karakter Unicode

Proses perhitungan tanda tangan

  1. Buat kebijakan yang dikodekan UTF-8.

  2. Buat string untuk ditandatangani.

    Kodekan Base64 kebijakan tersebut untuk menghasilkan string yang dapat ditransmisikan secara aman sebagai string yang akan ditandatangani.

  3. Hitung kunci penandatanganan.

    Enkripsi string yang akan ditandatangani menggunakan HMAC-SHA256. Gunakan kunci turunan dari akun sebagai kunci untuk menggunakan HMAC-SHA256.

  4. Hitung tanda tangan.

    Konversi hash biner yang dihitung menggunakan HMAC-SHA256 menjadi string heksadesimal. String heksadesimal yang diperoleh adalah tanda tangan yang digunakan untuk memverifikasi integritas dan validitas permintaan.

Contoh

  1. Kode sampel berikut memberikan contoh cara menggunakan kebijakan sebelumnya untuk menghitung tanda tangan V4 untuk permintaan PostObject menggunakan OSS SDK for Java:

    Gunakan Access Key (AK) atau Secret Key (SK)

    import com.aliyun.oss.common.utils.BinaryUtil;
    import org.apache.commons.codec.binary.Base64;
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    
    public class Demo {
        public static void main(String[] args) throws Exception {
            // Sebelum menjalankan kode sampel, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
            String accesskeyid =  System.getenv().get("OSS_ACCESS_KEY_ID");
            String accesskeysecret =  System.getenv().get("OSS_ACCESS_KEY_SECRET");
    
            // Langkah 1: Buat kebijakan.
            ObjectMapper mapper = new ObjectMapper();
    
            Map<String, Object> policy = new HashMap<>();
            policy.put("expiration", "2024-12-03T13:00:00.000Z");
    
            List<Object> conditions = new ArrayList<>();
    
            Map<String, String> bucketCondition = new HashMap<>();
            bucketCondition.put("bucket", "examplebucket");
            conditions.add(bucketCondition);
    
            Map<String, String> signatureVersionCondition = new HashMap<>();
            signatureVersionCondition.put("x-oss-signature-version", "OSS4-HMAC-SHA256");
            conditions.add(signatureVersionCondition);
    
            Map<String, String> credentialCondition = new HashMap<>();
            credentialCondition.put("x-oss-credential", "accesskeyid/20241203/cn-hangzhou/oss/aliyun_v4_request"); // Ganti variabel ini dengan ID AccessKey Anda.
            conditions.add(credentialCondition);
    
            Map<String, String> dateCondition = new HashMap<>();
            dateCondition.put("x-oss-date", "20241203T121212Z");
            conditions.add(dateCondition);
    
            conditions.add(Arrays.asList("content-length-range", 1, 10));
            conditions.add(Arrays.asList("eq", "$success_action_status", "201"));
            conditions.add(Arrays.asList("starts-with", "$key", "user/eric/"));
            conditions.add(Arrays.asList("in", "$content-type", Arrays.asList("image/jpg", "image/png")));
            conditions.add(Arrays.asList("not-in", "$cache-control", Arrays.asList("no-cache")));
    
            policy.put("conditions", conditions);
    
            String jsonPolicy = mapper.writeValueAsString(policy);
            // Langkah 2: Buat string untuk ditandatangani.
            String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes()));
            System.out.println(stringToSign)
            
            // Langkah 3: Hitung kunci penandatanganan.
            byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), "20231203");
            byte[] dateRegionKey = hmacsha256(dateKey, "cn-hangzhou");
            byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
            byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
    
            // Langkah 4: Hitung tanda tangan.
            byte[] result = hmacsha256(signingKey, stringToSign);
            String signature = BinaryUtil.toHex(result);
            System.out.println("signature:" + signature);
    
        }
    
        public static byte[] hmacsha256(byte[] key, String data) {
            try {
                // Inisialisasi SecretKeySpec, atur algoritma ke HMAC-SHA256, dan gunakan kunci yang disediakan.
                SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
    
                // Dapatkan instance Mac dan gunakan metode getInstance untuk mengatur algoritma ke HMAC-SHA256.
                Mac mac = Mac.getInstance("HmacSHA256");
                // Gunakan kunci untuk menginisialisasi instance Mac.
                mac.init(secretKeySpec);
    
                // Hitung nilai HMAC. Gunakan metode doFinal untuk menerima data yang akan dihitung dan mengembalikan hasil perhitungan sebagai array.
                byte[] hmacBytes = mac.doFinal(data.getBytes());
    
                return hmacBytes;
            } catch (Exception e) {
                throw new RuntimeException("Gagal menghitung HMAC-SHA256", e);
            }
        }
    }

    Respon sampel:

    signature:3908473f7dbfb79a102eaaa44ca1edec8d7058ce3bd1c624d59eb437463bd5d6

    Gunakan kredensial akses sementara

    Saat menghitung tanda tangan untuk permintaan PostObject menggunakan kredensial akses sementara, Anda juga perlu mendapatkan token keamanan dengan memanggil operasi AssumeRole STS.

    import com.aliyun.oss.common.utils.BinaryUtil;
    import org.apache.commons.codec.binary.Base64;
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import com.aliyun.sts20150401.models.AssumeRoleResponse;
    import com.aliyun.sts20150401.models.AssumeRoleResponseBody;
    import com.aliyun.tea.TeaException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.util.*;
    public class Demo {
    
        // Inisialisasi instance STSClient.
        public static com.aliyun.sts20150401.Client createStsClient() throws Exception {
            com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                    // Pastikan bahwa variabel lingkungan OSS_ACCESS_KEY_ID telah dikonfigurasi.
                    .setAccessKeyId(System.getenv("OSS_ACCESS_KEY_ID"))
                    // Pastikan bahwa variabel lingkungan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
                    .setAccessKeySecret(System.getenv("OSS_ACCESS_KEY_SECRET"));
            // Endpoint 
            config.endpoint = "sts.cn-hangzhou.aliyuncs.com";
            return new com.aliyun.sts20150401.Client(config);
        }
    
        // Dapatkan token STS.
        public static AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials getCredential() throws Exception {
            com.aliyun.sts20150401.Client client = Demo.createStsClient();
            com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest()
                    // Pastikan bahwa variabel lingkungan OSS_STS_ROLE_ARN telah dikonfigurasi.
                    .setRoleArn(System.getenv("OSS_STS_ROLE_ARN"))
                    .setRoleSessionName("role_session_name");// Tentukan nama sesi.
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            try {
                // Tulis kode Anda sendiri untuk menampilkan respons operasi API jika diperlukan.
                AssumeRoleResponse response = client.assumeRoleWithOptions(assumeRoleRequest, runtime);
                // AccessKey ID, AccessKey secret, dan token STS yang diperlukan untuk operasi selanjutnya termasuk dalam credentials.
                return response.body.credentials;
            } catch (TeaException error) {
                // Tangani pengecualian dengan hati-hati dalam skenario bisnis aktual Anda dan jangan pernah abaikan pengecualian dalam proyek Anda. Pesan kesalahan yang ditampilkan dalam contoh ini hanya untuk referensi.
                // Pesan kesalahan.
                System.out.println(error.getMessage());
                // URL untuk pemecahan masalah.
                System.out.println(error.getData().get("Recommend"));
                com.aliyun.teautil.Common.assertAsString(error.message);
            } catch (Exception _error) {
                TeaException error = new TeaException(_error.getMessage(), _error);
                // Tangani pengecualian dengan hati-hati dalam skenario bisnis aktual Anda dan jangan pernah abaikan pengecualian dalam proyek Anda. Pesan kesalahan yang ditampilkan dalam contoh ini hanya untuk referensi.
                // Pesan kesalahan.
                System.out.println(error.getMessage());
                // URL untuk pemecahan masalah.
                System.out.println(error.getData().get("Recommend"));
                com.aliyun.teautil.Common.assertAsString(error.message);
            }
            return null;
        }
    
        public static void main(String[] args) throws Exception {
    
            AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials sts_data = getCredential();
            String accesskeyid = sts_data.accessKeyId;
            String accesskeysecret = sts_data.accessKeySecret;
            String securitytoken = sts_data.securityToken;
            // Langkah 1: Buat kebijakan.
            ObjectMapper mapper = new ObjectMapper();
    
            Map<String, Object> policy = new HashMap<>();
            policy.put("expiration", "2024-12-03T13:00:00.000Z");
    
            List<Object> conditions = new ArrayList<>();
    
            Map<String, String> bucketCondition = new HashMap<>();
            bucketCondition.put("bucket", "examplebucket");
            conditions.add(bucketCondition);
    
            Map<String, String> signatureVersionCondition = new HashMap<>();
            signatureVersionCondition.put("x-oss-signature-version", "OSS4-HMAC-SHA256");
            conditions.add(signatureVersionCondition);
            
            Map<String, String> securityTokenCondition = new HashMap<>();
            securityTokenCondition.put("x-oss-security-token", securitytoken);
            conditions.add(securityTokenCondition);
            
            Map<String, String> credentialCondition = new HashMap<>();
            credentialCondition.put("x-oss-credential", "accesskeyid/20241203/cn-hangzhou/oss/aliyun_v4_request"); 
            conditions.add(credentialCondition);
    
            Map<String, String> dateCondition = new HashMap<>();
            dateCondition.put("x-oss-date", "20241203T121212Z");
            conditions.add(dateCondition);
    
            conditions.add(Arrays.asList("content-length-range", 1, 10));
            conditions.add(Arrays.asList("eq", "$success_action_status", "201"));
            conditions.add(Arrays.asList("starts-with", "$key", "user/eric/"));
            conditions.add(Arrays.asList("in", "$content-type", Arrays.asList("image/jpg", "image/png")));
            conditions.add(Arrays.asList("not-in", "$cache-control", Arrays.asList("no-cache")));
    
            policy.put("conditions", conditions);
    
            String jsonPolicy = mapper.writeValueAsString(policy);
            // Langkah 2: Buat string untuk ditandatangani.
            String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes()));
    
            // Langkah 3: Hitung kunci penandatanganan.
            byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), "20231203");
            byte[] dateRegionKey = hmacsha256(dateKey, "cn-hangzhou");
            byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
            byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
    
            // Langkah 4: Hitung tanda tangan.
            byte[] result = hmacsha256(signingKey, stringToSign);
            String signature = BinaryUtil.toHex(result);
            System.out.println("signature:" + signature);
    
        }
    
        public static byte[] hmacsha256(byte[] key, String data) {
            try {
                // Inisialisasi SecretKeySpec, atur algoritma ke HMAC-SHA256, dan gunakan kunci yang disediakan.
                SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
    
                // Dapatkan instance Mac dan gunakan metode getInstance untuk mengatur algoritma ke HMAC-SHA256.
                Mac mac = Mac.getInstance("HmacSHA256");
                // Gunakan kunci untuk menginisialisasi instance Mac.
                mac.init(secretKeySpec);
    
                // Hitung nilai HMAC. Gunakan metode doFinal untuk menerima data yang akan dihitung dan mengembalikan hasil perhitungan sebagai array.
                byte[] hmacBytes = mac.doFinal(data.getBytes());
    
                return hmacBytes;
            } catch (Exception e) {
                throw new RuntimeException("Gagal menghitung HMAC-SHA256", e);
            }
        }
    }

    Respon sampel:

    signature:1e09438f7ad01af6b3e144b42c98929c68f8d090ce07f4c277b18d8b62d0aa02
  2. Kode sampel berikut memberikan contoh cara menghitung tanda tangan V4 untuk permintaan PostObject menggunakan OSS SDK for Python:

    import base64
    import hmac
    import hashlib
    import os
    
    def hmac_sha256(key, data):
        return hmac.new(key, data.encode('utf-8'), hashlib.sha256).digest()
    
    # Ambil ID AccessKey dan rahasia AccessKey dari variabel lingkungan.    
    accesskeyid = os.getenv('OSS_ACCESS_KEY_ID')
    accesskeysecret = os.getenv('OSS_ACCESS_KEY_SECRET')
    
    # Tampilkan ID AccessKey.
    print(accesskeyid)
    
    # Periksa apakah variabel lingkungan telah diambil.
    if not accesskeyid or not accesskeysecret:
        raise ValueError("Variabel lingkungan yang diperlukan tidak ditemukan: OSS_ACCESS_KEY_ID atau OSS_ACCESS_KEY_SECRET")
    
    # Buat kebijakan.
    policy = '''{
      "expiration": "2025-01-01T00:00:00.000Z",
      "conditions": [
        {"x-oss-signature-version": "OSS4-HMAC-SHA256"},
        {"x-oss-credential": "accesskeyid/20241105/cn-hangzhou/oss/aliyun_v4_request"}, // Ganti accesskeyid dengan ID access key Anda yang sebenarnya.
        {"x-oss-date": "20241105T065000Z"}
      ]
    }'''
    
    # Keluarkan kebijakan.
    print(policy)
    
    # Hitung string untuk ditandatangani.
    string_to_sign = base64.b64encode(policy.encode('utf-8')).decode('utf-8')
    print(string_to_sign)
    
    # Hitung kunci penandatanganan.
    date_key = hmac_sha256(f"aliyun_v4{accesskeysecret}".encode('utf-8'), "20241105")
    date_region_key = hmac_sha256(date_key, "cn-beijing")
    date_region_service_key = hmac_sha256(date_region_key, "oss")
    signing_key = hmac_sha256(date_region_service_key, "aliyun_v4_request")
    
    # Hitung tanda tangan.
    result = hmac_sha256(signing_key, string_to_sign)
    signature = result.hex()
    print("signature:", signature)

    Respon sampel:

    signature:9e85d56429245283b1aca5bc2dc31e0020b95ac2de9e9b81b496994db602ba1e