All Products
Search
Document Center

Object Storage Service:Penandatanganan sisi server untuk unggah langsung

Last Updated:Sep 02, 2026

Operasi PostObject memungkinkan Anda mengunggah file langsung dari klien web ke Object Storage Service (OSS). Operasi ini menggunakan signature yang dihasilkan oleh server demi keamanan dan memungkinkan Anda mengonfigurasi kebijakan untuk membatasi unggahan sesuai kebutuhan bisnis.

Ikhtisar solusi

Untuk menerapkan unggah langsung dengan penandatanganan sisi server, ikuti tiga langkah berikut:

Catatan

Penggunaan kredensial akses temporary mencegah terpaparnya kunci jangka panjang server Anda, sehingga meningkatkan keamanan unggah file.

  1. Konfigurasikan OSS: Buat bucket di konsol untuk menyimpan file pengguna, lalu konfigurasikan aturan Cross-Origin Resource Sharing (CORS) agar bucket mengizinkan permintaan lintas asal dari klien web.

  2. Konfigurasikan server: Panggil Security Token Service (STS) untuk mendapatkan kredensial akses temporary, lalu gunakan kredensial tersebut beserta kebijakan unggah sisi server untuk menghasilkan signature. Kebijakan ini mencakup parameter seperti nama bucket, path direktori, dan waktu kedaluwarsa. Signature ini memberi otorisasi kepada pengguna untuk mengunggah file dalam periode tertentu.

  3. Konfigurasikan klien web: Susun permintaan formulir HTML dan gunakan signature tersebut untuk mengunggah file ke OSS.

Proyek contoh

Langkah-langkah

Langkah 1: Konfigurasikan OSS

Buat bucket

Buat bucket OSS untuk menyimpan file yang diunggah langsung dari browser web.

  1. Login ke Konsol OSS.

  2. Pada panel navigasi kiri, klik Buckets, lalu klik Create Bucket.

  3. Pada panel Create Bucket, pilih Quick Create dan konfigurasikan parameter berikut:

    Parameter

    Nilai contoh

    Bucket Name

    web-direct-upload

    Region

    China (Hangzhou)

  4. Klik Create.

Konfigurasikan aturan CORS

Konfigurasikan aturan CORS untuk bucket OSS Anda.

  1. Pada halaman Buckets, klik bucket target.

  2. Pada halaman CORS, klik Create Rule.

  3. Pada panel Create Rule, atur parameter berikut.

    Parameter

    Nilai contoh

    Origin

    *

    Allowed Methods

    POST, PUT, GET

    Allowed Headers

    *

  1. Klik OK.

Langkah 2: Konfigurasikan server

Catatan

Untuk penerapan produksi, jika Anda sudah memiliki server, lewati persiapan dan langsung menuju 1. Konfigurasikan izin pengguna.

Buat instance ECS

Langkah 1: Buat instance ECS

Buka halaman Custom Launch dan pilih sumber daya dasar yang diperlukan untuk membuat instance ECS.

  1. Pilih wilayah dan metode penagihan

    1. Pilih metode penagihan sesuai kebutuhan bisnis Anda. Tutorial ini menggunakan mode pay-as-you-go karena fleksibilitasnya.

    2. Umumnya, memilih wilayah yang lebih dekat dengan pengguna Anda menghasilkan latensi jaringan lebih rendah dan akses lebih cepat. Tutorial ini menggunakan China (Hangzhou) sebagai contoh.

      Untuk Billing Method, pilih pay-as-you-go (post-paid dan on-demand). Instance pay-as-you-go tidak mendukung Pendaftaran ICP. Setelah instance dibuat, wilayahnya tidak dapat diubah. Instance di wilayah berbeda tidak dapat berkomunikasi melalui jaringan internal.

  1. Buat Virtual Private Cloud (VPC) dan vSwitch

    Saat membuat VPC, pilih wilayah yang sama dengan instance ECS dan rencanakan Blok CIDR sesuai kebutuhan bisnis Anda. Tutorial ini menggunakan pembuatan VPC dan vSwitch di wilayah China (Hangzhou) sebagai contoh. Setelah membuat VPC dan vSwitch, kembali ke halaman pembelian ECS, refresh, lalu pilih keduanya.

    Catatan

    Anda dapat membuat vSwitch saat membuat VPC.

    Pada halaman Create VPC, atur Name menjadi ProjectA-VPC, pilih Manually Specify IPv4 CIDR Block untuk IPv4 CIDR Block dan masukkan 192.168.0.0/16, serta pilih Do Not Assign untuk IPv6 CIDR Block.

    Konfigurasi vSwitch contoh: Atur Name menjadi ProjectA-vSwitch, pilih Hangzhou Zone H untuk Zone, atur IPv4 CIDR Block menjadi 192.168.10.0/24, lalu klik OK.

  1. Pilih tipe instans dan gambar

    Pilih tipe instans dan gambar. Gambar menentukan sistem operasi dan versinya yang diinstal pada instans. Tutorial ini menggunakan tipe instans ecs.e-c1m1.large, yang hemat biaya dan memenuhi kebutuhan pengujian. Gambarnya adalah gambar publik Alibaba Cloud Linux 3.2104 LTS 64-bit.

  1. Konfigurasikan penyimpanan

    Untuk sistem web sederhana dalam tutorial ini, disk sistem sudah cukup untuk sistem operasi, sehingga tidak diperlukan disk data.

    Untuk disk sistem, pilih ESSD, atur Performance Level ke PL0 dan Kapasitas ke 40 GiB, pilih Release with Instance, dan jangan tambahkan disk data.

  1. Tetapkan Alamat IP publik

    Untuk kesederhanaan, tutorial ini langsung menetapkan Alamat IP publik ke instans. Alternatifnya, Anda dapat mengaitkan Elastic IP Address (EIP) ke instans setelah membuatnya. Untuk informasi selengkapnya, lihat Mengaitkan EIP dengan sumber daya cloud.

    Catatan
    • Jika Alamat IP publik tidak ditetapkan, Anda tidak dapat menggunakan SSH atau Remote Desktop Protocol (RDP) untuk mengakses instans secara langsung dari internet, maupun memverifikasi penerapan layanan web pada instans tersebut.

    • Tutorial ini menggunakan metode penagihan bandwidth pay-by-traffic. Metode ini hanya menagih Anda berdasarkan trafik publik yang dikonsumsi. Untuk informasi selengkapnya, lihat Penagihan bandwidth publik.

    Atur Peak bandwidth ke 5 Mbps.

  1. Buat grup keamanan

    Buat grup keamanan untuk instans tersebut. Grup keamanan adalah firewall virtual yang mengontrol lalu lintas arah masuk dan keluar untuk instance ECS. Saat membuat grup keamanan, izinkan lalu lintas pada port berikut agar Anda dapat mengakses instance ECS nanti.

    Port range: SSH (22), RDP (3389), HTTP (80), dan HTTPS (443).

    Catatan
    • Port yang dipilih untuk Port range diperlukan oleh aplikasi yang berjalan pada instance ECS.

    • Secara default, grup keamanan yang dibuat di sini mencakup aturan yang menetapkan source ke 0.0.0.0/0. Hal ini mengizinkan akses dari alamat IP mana pun ke port yang ditentukan. Jika Anda mengetahui alamat IP klien yang melakukan permintaan, kami merekomendasikan agar Anda kemudian membatasi source ke rentang IP tertentu. Untuk informasi selengkapnya, lihat Memodifikasi aturan grup keamanan.

    Pada bagian Security group type, pilih Basic security group.

  1. Buat pasangan kunci

    1. Pasangan kunci menyediakan kredensial logon yang aman. Setelah membuat pasangan kunci, Anda harus mengunduh kunci privatnya, yang diperlukan untuk menghubungkan ke instance ECS. Lalu, kembali ke halaman pembelian ECS, refresh, dan pilih pasangan kunci tersebut.

    2. Pengguna root memiliki hak istimewa tertinggi dalam sistem operasi, dan menggunakan root sebagai nama login dapat menimbulkan risiko keamanan. Kami merekomendasikan agar Anda menggunakan ecs-user sebagai nama login.

      Catatan

      Setelah membuat pasangan kunci, kunci privat akan diunduh secara otomatis. Simpan file kunci privat .pem dari riwayat unduhan browser Anda.

      Pada bagian Logon Credential, pilih tab Key pair, klik Create key pair. Lalu, pilih pasangan kunci yang baru dibuat (misalnya, ecs-test) dari daftar drop-down Key pair.

  1. Buat dan lihat instance ECS

    Setelah memilih sumber daya yang diperlukan untuk instance ECS, klik Create order. Di kotak dialog sukses, klik Management console untuk melihat instance baru. Simpan informasi berikut untuk digunakan nanti:

    • Instance ID: Digunakan untuk menemukan instance dalam daftar instance.

    • Region: Digunakan untuk menemukan instance dalam daftar instance.

    • Public IP address: Digunakan untuk memverifikasi penerapan layanan web.

Langkah 2: Hubungkan ke instance ECS

  1. Pada halaman Instances di Konsol ECS, temukan instance Anda menggunakan wilayah dan ID-nya, lalu pada kolom Actions, klik Connect.

  2. Pada kotak dialog Remote connection, klik Sign in now di sebelah Workbench.

  3. Pada kotak dialog Log on to instance, pilih Terminal connection untuk Connection method dan SSH key authentication untuk Authentication method. Lalu, masukkan atau unggah file kunci privat Anda, dan klik Log on untuk terhubung sebagai pengguna ecs-user.

  4. Catatan

    File kunci privat (.pem) diunduh secara otomatis ke perangkat Anda saat membuat pasangan kunci. Periksa riwayat unduhan browser Anda untuk menemukan file tersebut.

  5. Saat output berikut ditampilkan, Anda telah berhasil login ke instance ECS.

    Welcome to Alibaba Cloud Elastic Compute Service !
    Last login: Sun Sep 29 15:35:22 2024 from xxx
    [ecs-user@iz*** ~]$

Izin pengguna

Catatan

Untuk mencegah unggahan OSS gagal setelah penerapan akibat izin yang tidak mencukupi, buat pengguna RAM dan konfigurasikan izin yang diperlukan.

Langkah 1: Buat pengguna RAM

Buat pengguna RAM dan dapatkan Pasangan Kunci Aksesnya untuk berfungsi sebagai kredensial jangka panjang bagi server aplikasi Anda.

  1. Login ke Konsol RAM dengan Akun Alibaba Cloud Anda atau sebagai administrator RAM.

  2. Pada panel navigasi kiri, pilih Identities > Users.

  3. Klik Create User.

  4. Masukkan Logon Name dan Display Name.

  5. Pada bagian Access Mode, pilih Programmatic access, lalu klik OK.

Penting

Rahasia AccessKey hanya ditampilkan saat pembuatan dan tidak dapat diambil kembali nanti. Simpan dengan aman.

  1. Pada kolom Actions, klik Copy untuk menyimpan Pasangan Kunci Akses (ID AccessKey dan Rahasia AccessKey).

Langkah 2: Berikan izin AssumeRole

Setelah membuat pengguna RAM, berikan izin untuk memanggil operasi STS AssumeRole. Hal ini memungkinkan pengguna memperoleh kredensial temporary dengan mengasumsikan peran RAM.

  1. Pada panel navigasi kiri, pilih Identities > Users.

  2. Pada halaman Users, temukan pengguna RAM target, lalu klik Add Permissions di kolom Actions.

  3. Pada halaman Grant Permission, pilih Kebijakan Sistem AliyunSTSAssumeRoleAccess.

    Catatan

    Kebijakan AliyunSTSAssumeRoleAccess memberikan izin untuk memanggil operasi AssumeRole. Kebijakan ini tidak memberikan izin untuk operasi selanjutnya yang menggunakan kredensial temporary, seperti permintaan OSS.

  4. Klik OK.

Langkah 3: Buat peran RAM

Buat peran RAM untuk Akun Alibaba Cloud saat ini dan dapatkan Nama Sumber Daya Alibaba Cloud (ARN)-nya. Pengguna RAM akan mengasumsikan peran ini.

  1. Pada panel navigasi kiri, pilih Identities > Roles.

  2. Klik Create Role. Untuk Principal Type, pilih Alibaba Cloud Account.

  3. Pilih Akun Alibaba Cloud saat ini dan klik OK.

  4. Masukkan nama peran dan klik OK.

  5. Pada halaman detail peran RAM, klik Copy untuk menyimpan ARN peran tersebut.

Langkah 4: Buat kebijakan unggah file

Dengan mengikuti prinsip Hak istimewa minimal, buat Kebijakan Kustom untuk peran RAM yang membatasi unggahan ke bucket OSS tertentu.

  1. Pada panel navigasi kiri, pilih Permissions > Policies.

  2. Klik Create Policy.

  3. Pada halaman Create Policy, klik JSON Editor dan ganti <Bucket name> dalam skrip dengan nama bucket web-direct-upload yang Anda buat di bagian Persiapan.

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "oss:PutObject",
          "Resource": "acs:oss:*:*:<BucketName>/*"
        }
      ]
    }
  4. Setelah mengonfigurasi kebijakan, klik OK.

  5. Pada kotak dialog Create Policy, masukkan Policy Name dan klik OK.

Langkah 5: Berikan izin ke peran RAM

Berikan Kebijakan Kustom yang Anda buat ke peran RAM. Hal ini memberikan izin yang diperlukan kepada peran yang diasumsikan.

  1. Pada panel navigasi kiri, pilih Identities > Roles.

  2. Pada halaman Roles, temukan peran RAM target, lalu klik Add Permissions di kolom Actions.

  3. Pada halaman Grant Permission, pilih Custom Policy, lalu pilih kebijakan yang Anda buat.

  4. Klik OK.

Signature sisi server

Catatan

Kami merekomendasikan mengonfigurasi informasi sensitif, seperti AccessKey ID, AccessKey Secret, dan Role ARN, sebagai Variabel lingkungan. Praktik ini menghindari hardcoding dalam kode Anda dan mengurangi risiko kebocoran kredensial.

Ikuti langkah-langkah berikut untuk menetapkan variabel lingkungan.

Linux

  1. Dari command line, jalankan perintah berikut untuk menambahkan pengaturan variabel lingkungan ke file ~/.bashrc.

    echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.bashrc
    echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.bashrc
    echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.bashrc
  2. Jalankan perintah berikut untuk menerapkan perubahan.

    source  ~/.bashrc
  3. Jalankan perintah berikut untuk memverifikasi bahwa variabel lingkungan telah ditetapkan.

    echo $OSS_ACCESS_KEY_ID
    echo $OSS_ACCESS_KEY_SECRET
    echo $OSS_STS_ROLE_ARN

macOS

  1. Di terminal, jalankan perintah berikut untuk memeriksa shell default Anda.

    echo $SHELL
  2. Ikuti petunjuk untuk shell default Anda.

    Zsh

    1. Jalankan perintah berikut untuk menambahkan pengaturan variabel lingkungan ke file ~/.zshrc.

      echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.zshrc
      echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.zshrc
      echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.zshrc
    2. Jalankan perintah berikut untuk menerapkan perubahan.

      source ~/.zshrc
    3. Jalankan perintah berikut untuk memverifikasi bahwa variabel lingkungan telah ditetapkan.

      echo $OSS_ACCESS_KEY_ID
      echo $OSS_ACCESS_KEY_SECRET
      echo $OSS_STS_ROLE_ARN

    Bash

    1. Jalankan perintah berikut untuk menambahkan pengaturan variabel lingkungan ke file ~/.bash_profile.

      echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.bash_profile
      echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.bash_profile
      echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.bash_profile
    2. Jalankan perintah berikut untuk menerapkan perubahan.

      source ~/.bash_profile
    3. Jalankan perintah berikut untuk memverifikasi bahwa variabel lingkungan telah ditetapkan.

      echo $OSS_ACCESS_KEY_ID
      echo $OSS_ACCESS_KEY_SECRET
      echo $OSS_STS_ROLE_ARN

Windows

  1. Jalankan perintah berikut di Command Prompt (CMD).

    setx OSS_ACCESS_KEY_ID "your-access-key-id"
    setx OSS_ACCESS_KEY_SECRET "your-access-key-secret"
    setx OSS_STS_ROLE_ARN "your-role-arn"
  2. Buka jendela CMD baru.

  3. Di jendela CMD baru, jalankan perintah berikut untuk memverifikasi bahwa variabel lingkungan telah ditetapkan.

    echo %OSS_ACCESS_KEY_ID%
    echo %OSS_ACCESS_KEY_SECRET%
    echo %OSS_STS_ROLE_ARN%

Gunakan kode contoh berikut untuk menghitung signature POST di server dengan Signature Version 4 (direkomendasikan). Untuk informasi selengkapnya tentang mengonfigurasi field form policy, lihat field form policy.

Java

Tambahkan dependensi berikut ke proyek Maven Anda.

<!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.17.4</version>
</dependency>
<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>sts20150401</artifactId>
  <version>1.1.6</version>
</dependency>

Kode contoh berikut menunjukkan cara mendapatkan kredensial akses temporary dan menghitung signature POST di server:

package com.aliyun.oss.web;
import com.aliyun.sts20150401.models.AssumeRoleResponse;
import com.aliyun.sts20150401.models.AssumeRoleResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Controller
public class WebController {
    // Informasi dasar OSS. Ganti dengan nama bucket, ID wilayah, dan host aktual Anda.
    String bucket = "examplebucket";
    String region = "cn-hangzhou";
    String host = "http://examplebucket.oss-cn-hangzhou.aliyuncs.com";
    // Tetapkan URL callback unggahan, yaitu alamat server callback Anda. Ini harus berupa URL publik. OSS menggunakan URL ini untuk mengirim informasi unggahan objek ke server aplikasi Anda.
    // Awalan (direktori) untuk objek yang akan diunggah ke OSS.
    String upload_dir = "dir";
    // Waktu kedaluwarsa dalam detik.
    Long expire_time = 3600L;
    /**
     * Menghasilkan waktu kedaluwarsa berdasarkan durasi tertentu dalam detik.
     * @param seconds Durasi dalam detik.
     * @return String waktu ISO 8601, seperti "2014-12-01T12:00:00.000Z".
     */
    public static String generateExpiration(long seconds) {
        // Dapatkan timestamp saat ini dalam detik.
        long now = Instant.now().getEpochSecond();
        // Hitung timestamp kedaluwarsa.
        long expirationTime = now + seconds;
        // Konversi timestamp ke objek Instant dan format ke ISO 8601.
        Instant instant = Instant.ofEpochSecond(expirationTime);
        // Tentukan zona waktu sebagai UTC.
        ZoneId zone = ZoneOffset.UTC;  
        // Konversi Instant ke ZonedDateTime.
        ZonedDateTime zonedDateTime = instant.atZone(zone);
        // Tentukan format tanggal-waktu, misalnya, 2023-12-03T13:00:00.000Z.
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        // Format tanggal dan waktu.
        String formattedDate = zonedDateTime.format(formatter);
        // Kembalikan hasilnya.
        return formattedDate;
    }
    // Inisialisasi klien STS.
    public static com.aliyun.sts20150401.Client createStsClient() throws Exception {
        // Hardcoding pasangan AccessKey merupakan risiko keamanan dan tidak direkomendasikan. Kode ini hanya untuk referensi.
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // Wajib. Pastikan variabel lingkungan OSS_ACCESS_KEY_ID ditetapkan di lingkungan runtime kode Anda.
                .setAccessKeyId(System.getenv("OSS_ACCESS_KEY_ID"))
                // Wajib. Pastikan variabel lingkungan OSS_ACCESS_KEY_SECRET ditetapkan di lingkungan runtime kode Anda.
                .setAccessKeySecret(System.getenv("OSS_ACCESS_KEY_SECRET"));
        // Untuk informasi selengkapnya tentang endpoint, lihat https://api.alibabacloud.com/product/Sts.
        config.endpoint = "sts.cn-hangzhou.aliyuncs.com";
        return new com.aliyun.sts20150401.Client(config);
    }
    /**
     * Dapatkan kredensial temporary STS.
     * @return Objek AssumeRoleResponseBodyCredentials.
     */
    public static AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials getCredential() throws Exception {
        com.aliyun.sts20150401.Client client = WebController.createStsClient();
        com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest()
                // Wajib. Pastikan variabel lingkungan OSS_STS_ROLE_ARN ditetapkan di lingkungan runtime kode Anda.
                .setRoleArn(System.getenv("OSS_STS_ROLE_ARN"))
                .setRoleSessionName("yourRoleSessionName");// Nama sesi kustom.
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try {
            // Jika Anda menyalin kode ini untuk dijalankan, cetak nilai kembali API.
            AssumeRoleResponse response = client.assumeRoleWithOptions(assumeRoleRequest, runtime);
            // Objek kredensial berisi AccessKeyId, AccessKeySecret, dan SecurityToken.
            return response.body.credentials;
        } catch (TeaException error) {
            // Ini hanya untuk demonstrasi. Tangani pengecualian dengan hati-hati dan jangan abaikan dalam proyek Anda.
            // Pesan error
            System.out.println(error.getMessage());
            // Alamat diagnostik
            System.out.println(error.getData().get("Recommend"));
            com.aliyun.teautil.Common.assertAsString(error.message);
        }
        // Kembalikan objek respons error default untuk menghindari pengembalian null.
        AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials defaultCredentials = new AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials();
        defaultCredentials.accessKeyId = "ERROR_ACCESS_KEY_ID";
        defaultCredentials.accessKeySecret = "ERROR_ACCESS_KEY_SECRET";
        defaultCredentials.securityToken = "ERROR_SECURITY_TOKEN";
        return defaultCredentials;
    }
    @GetMapping("/get_post_signature_for_oss_upload")
    public ResponseEntity<Map<String, String>> getPostSignatureForOssUpload() throws Exception {
        AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials sts_data = getCredential();
        String accesskeyid =  sts_data.accessKeyId;
        String accesskeysecret =  sts_data.accessKeySecret;
        String securitytoken =  sts_data.securityToken;
       // Dapatkan tanggal untuk x-oss-credential. Ini adalah tanggal saat ini dalam format yyyyMMdd.
        ZonedDateTime today = ZonedDateTime.now().withZoneSameInstant(java.time.ZoneOffset.UTC);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String date = today.format(formatter);
        // Dapatkan x-oss-date.
        ZonedDateTime now = ZonedDateTime.now().withZoneSameInstant(java.time.ZoneOffset.UTC);
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'");
        String x_oss_date = now.format(formatter2);
        // Langkah 1: Buat kebijakan.
        String x_oss_credential = accesskeyid + "/" + date + "/" + region + "/oss/aliyun_v4_request";
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> policy = new HashMap<>();
        policy.put("expiration", generateExpiration(expire_time));
        List<Object> conditions = new ArrayList<>();
        Map<String, String> bucketCondition = new HashMap<>();
        bucketCondition.put("bucket", bucket);
        conditions.add(bucketCondition);
        Map<String, String> securityTokenCondition = new HashMap<>();
        securityTokenCondition.put("x-oss-security-token", securitytoken);
        conditions.add(securityTokenCondition);
        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", x_oss_credential); // Ganti dengan ID AccessKey aktual Anda.
        conditions.add(credentialCondition);
        Map<String, String> dateCondition = new HashMap<>();
        dateCondition.put("x-oss-date", x_oss_date);
        conditions.add(dateCondition);
        conditions.add(Arrays.asList("content-length-range", 1, 10240000));
        conditions.add(Arrays.asList("eq", "$success_action_status", "200"));
        conditions.add(Arrays.asList("starts-with", "$key", upload_dir));
        policy.put("conditions", conditions);
        String jsonPolicy = mapper.writeValueAsString(policy);
        // Langkah 2: Susun string untuk ditandatangani.
        String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes()));
        // System.out.println("stringToSign: " + stringToSign);
        // Langkah 3: Hitung kunci penandatanganan.
        byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), date);
        byte[] dateRegionKey = hmacsha256(dateKey, region);
        byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
        byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
        // System.out.println("signingKey: " + BinaryUtil.toBase64String(signingKey));
        // Langkah 4: Hitung signature.
        byte[] result = hmacsha256(signingKey, stringToSign);
        String signature = BinaryUtil.toHex(result);
        // System.out.println("signature:" + signature);
        Map<String, String> response = new HashMap<>();
        // Tambahkan data ke map.
        response.put("version", "OSS4-HMAC-SHA256");
        response.put("policy", stringToSign);
        response.put("x_oss_credential", x_oss_credential);
        response.put("x_oss_date", x_oss_date);
        response.put("signature", signature);
        response.put("security_token", securitytoken);
        response.put("dir", upload_dir);
        response.put("host", host);
        // Kembalikan ResponseEntity dengan kode status 200 (OK) ke klien web untuk operasi PostObject.
        return ResponseEntity.ok(response);
    }
    public static byte[] hmacsha256(byte[] key, String data) {
        try {
            // Inisialisasi spesifikasi kunci HmacSHA256.
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
            // Dapatkan instance Mac HmacSHA256.
            Mac mac = Mac.getInstance("HmacSHA256");
            // Inisialisasi objek Mac dengan kunci.
            mac.init(secretKeySpec);
            // Hitung signature HMAC untuk data.
            byte[] hmacBytes = mac.doFinal(data.getBytes());
            return hmacBytes;
        } catch (Exception e) {
            throw new RuntimeException("Gagal menghitung HMAC-SHA256", e);
        }
    }
}

Python

Jalankan perintah berikut untuk menginstal dependensi.

pip install flask
pip install alibabacloud_tea_openapi alibabacloud_sts20150401 alibabacloud_credentials

Kode contoh berikut menunjukkan cara mendapatkan kredensial akses temporary (token STS), menyusun kebijakan unggahan, dan menghitung signature POST di server.

from flask import Flask, render_template, jsonify
from alibabacloud_tea_openapi.models import Config
from alibabacloud_sts20150401.client import Client as Sts20150401Client
from alibabacloud_sts20150401 import models as sts_20150401_models
from alibabacloud_credentials.client import Client as CredentialClient
import os
import json
import base64
import hmac
import datetime
import time
import hashlib
app = Flask(__name__)
# Konfigurasikan variabel lingkungan OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, dan OSS_STS_ROLE_ARN.
access_key_id = os.environ.get('OSS_ACCESS_KEY_ID')
access_key_secret = os.environ.get('OSS_ACCESS_KEY_SECRET')
role_arn_for_oss_upload = os.environ.get('OSS_STS_ROLE_ARN')
# Nama sesi kustom.
role_session_name = 'yourRoleSessionName'  
# Ganti dengan nama bucket, ID Wilayah, dan Host Anda yang sebenarnya.
bucket = 'examplebucket'
region_id = 'cn-hangzhou'
host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'
# Waktu kedaluwarsa dalam detik.
expire_time = 3600  
# Awalan (direktori) untuk objek yang akan diunggah ke OSS.
upload_dir = 'dir'
def hmacsha256(key, data):
    """
    Menghitung nilai hash HMAC-SHA256.
    :param key: Kunci untuk menghitung hash, dalam byte.
    :param data: Data yang akan di-hash, sebagai string.
    :return: Nilai hash HMAC-SHA256 yang dihitung, dalam byte.
    """
    try:
        mac = hmac.new(key, data.encode(), hashlib.sha256)
        hmacBytes = mac.digest()
        return hmacBytes
    except Exception as e:
        raise RuntimeError(f"Gagal menghitung HMAC-SHA256 karena {e}")
@app.route("/")
def hello_world():
    return render_template('index.html')
@app.route('/get_post_signature_for_oss_upload', methods=['GET'])
def generate_upload_params():
    # Inisialisasi konfigurasi dan teruskan kredensial secara langsung.
    config = Config(
        region_id=region_id,
        access_key_id=access_key_id,
        access_key_secret=access_key_secret
    )
    # Buat Klien STS dan dapatkan kredensial sementara.
    sts_client = Sts20150401Client(config=config)
    assume_role_request = sts_20150401_models.AssumeRoleRequest(
        role_arn=role_arn_for_oss_upload,
        role_session_name=role_session_name
    )
    response = sts_client.assume_role(assume_role_request)
    token_data = response.body.credentials.to_map()
    # Gunakan kredensial sementara yang dikembalikan oleh STS.
    temp_access_key_id = token_data['AccessKeyId']
    temp_access_key_secret = token_data['AccessKeySecret']
    security_token = token_data['SecurityToken']
    now = int(time.time())
    # Konversikan stempel waktu ke objek datetime.
    dt_obj = datetime.datetime.utcfromtimestamp(now)
    # Tambahkan 3 jam ke waktu saat ini untuk mengatur waktu kedaluwarsa permintaan.
    dt_obj_plus_3h = dt_obj + datetime.timedelta(hours=3)
    # Waktu permintaan.
    dt_obj_1 = dt_obj.strftime('%Y%m%dT%H%M%S') + 'Z'
    # Tanggal permintaan.
    dt_obj_2 = dt_obj.strftime('%Y%m%d')
    # Waktu kedaluwarsa permintaan.
    expiration_time = dt_obj_plus_3h.strftime('%Y-%m-%dT%H:%M:%S.000Z')
    # Buat Kebijakan dan buat tanda tangan.
    policy = {
        "expiration": expiration_time,
        "conditions": [
            ["eq", "$success_action_status", "200"],
            {"x-oss-signature-version": "OSS4-HMAC-SHA256"},
            {"x-oss-credential": f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request"},
            {"x-oss-security-token": security_token},
            {"x-oss-date": dt_obj_1},  
        ]
    }
    print(dt_obj_1)
    policy_str = json.dumps(policy).strip()
    # Langkah 2: Buat string yang akan ditandatangani.
    stringToSign = base64.b64encode(policy_str.encode()).decode()
    # Langkah 3: Hitung kunci penandatanganan.
    dateKey = hmacsha256(("aliyun_v4" + temp_access_key_secret).encode(), dt_obj_2)
    dateRegionKey = hmacsha256(dateKey, "cn-hangzhou")
    dateRegionServiceKey = hmacsha256(dateRegionKey, "oss")
    signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request")
    # Langkah 4: Hitung tanda tangan.
    result = hmacsha256(signingKey, stringToSign)
    signature = result.hex()
    # Buat data tanggapan.
    response_data = {
        'policy': stringToSign,  # Bidang formulir kebijakan.
        'x_oss_signature_version': "OSS4-HMAC-SHA256",  # Versi dan algoritma tanda tangan. Ini ditetapkan ke OSS4-HMAC-SHA256.
        'x_oss_credential': f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request",  # Menentukan cakupan kredensial.
        'x_oss_date': dt_obj_1,  # Waktu permintaan.
        'signature': signature,  # Tanda tangan yang dihitung.
        'host': host,
        'dir': upload_dir,
        'security_token': security_token  # Token keamanan.
    }
    return jsonify(response_data)
if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8000)  # Jika Anda perlu mendengarkan di alamat lain seperti 0.0.0.0, Anda harus menambahkan mekanisme otentikasi sisi server.

Node.js

Jalankan perintah berikut untuk menginstal dependensi.

npm install ali-oss
npm install @alicloud/credentials
npm install express

Kode contoh berikut menunjukkan cara mendapatkan kredensial akses temporary (token STS), menyusun kebijakan unggahan, dan menghitung signature POST di server.

const express = require('express');
const OSS = require('ali-oss');
const { STS } = require('ali-oss');
const { getCredential } = require('ali-oss/lib/common/signUtils');
const { getStandardRegion } = require('ali-oss/lib/common/utils/getStandardRegion');
const { policy2Str } = require('ali-oss/lib/common/utils/policy2Str');
const app = express();
const PORT = process.env.PORT || 8000; // Nomor port untuk permintaan layanan.
// Tetapkan direktori file statis.
app.use(express.static('templates'));
const GenerateSignature = async () => {
    // Inisialisasi klien STS.
    let sts = new STS({
        accessKeyId: process.env.OSS_ACCESS_KEY_ID,  // Dapatkan ID AccessKey pengguna RAM dari variabel lingkungan.
        accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET // Dapatkan Rahasia AccessKey pengguna RAM dari variabel lingkungan.
    });
    // Panggil operasi assumeRole untuk mendapatkan kredensial akses STS temporary.
    const result = await sts.assumeRole(process.env.OSS_STS_ROLE_ARN, '', '3600', 'yourRoleSessionName'); // Dapatkan ARN peran RAM dari variabel lingkungan. Kredensial akses temporary berlaku selama 3.600 detik, dan nama sesi peran adalah nilai kustom, seperti yourRoleSessionName.
    // Ekstrak AccessKeyId, AccessKeySecret, dan SecurityToken dari kredensial akses temporary.
    const accessKeyId = result.credentials.AccessKeyId;
    const accessKeySecret = result.credentials.AccessKeySecret;
    const securityToken = result.credentials.SecurityToken;
    // Inisialisasi klien OSS.
    const client = new OSS({
        bucket: 'examplebucket', // Ganti dengan nama bucket tujuan.
        region: 'cn-hangzhou', // Ganti dengan wilayah bucket tujuan.
        accessKeyId,
        accessKeySecret,
        stsToken: securityToken,
        refreshSTSTokenInterval: 0,
        refreshSTSToken: async () => {
            const { accessKeyId, accessKeySecret, securityToken } = await client.getCredential();
            return { accessKeyId, accessKeySecret, stsToken: securityToken };
        },
    });
    // Buat map data form.
    const formData = new Map();
    // Tetapkan waktu kedaluwarsa signature ke 10 menit dari waktu saat ini. 
    const date = new Date();
    const expirationDate = new Date(date);
    expirationDate.setMinutes(date.getMinutes() + 10);
    // Format tanggal ke string waktu UTC yang sesuai dengan ISO 8601.
    function padTo2Digits(num) {
        return num.toString().padStart(2, '0');
    }
    function formatDateToUTC(date) {
        return (
            date.getUTCFullYear() +
            padTo2Digits(date.getUTCMonth() + 1) +
            padTo2Digits(date.getUTCDate()) +
            'T' +
            padTo2Digits(date.getUTCHours()) +
            padTo2Digits(date.getUTCMinutes()) +
            padTo2Digits(date.getUTCSeconds()) +
            'Z'
        );
    }
    const formattedDate = formatDateToUTC(expirationDate);
    // Hasilkan x-oss-credential dan tetapkan data form.
    const credential = getCredential(formattedDate.split('T')[0], getStandardRegion(client.options.region), client.options.accessKeyId);
    formData.set('x_oss_date', formattedDate);
    formData.set('x_oss_credential', credential);
    formData.set('x_oss_signature_version', 'OSS4-HMAC-SHA256');
    // Buat kebijakan.
    // Kebijakan contoh ini hanya mencantumkan kondisi yang diperlukan.
    const policy = {
        expiration: expirationDate.toISOString(),
        conditions: [
            { 'bucket': 'examplebucket'}, 
            { 'x-oss-credential': credential },
            { 'x-oss-signature-version': 'OSS4-HMAC-SHA256' },
            { 'x-oss-date': formattedDate },
        ],
    };
    // Jika ada token STS, tambahkan ke kebijakan dan data form.
    if (client.options.stsToken) {
        policy.conditions.push({ 'x-oss-security-token': client.options.stsToken });
        formData.set('security_token', client.options.stsToken);
    }
    // Hasilkan signature dan tetapkan data form.
    const signature = client.signPostObjectPolicyV4(policy, date);
    formData.set('policy', Buffer.from(policy2Str(policy), 'utf8').toString('base64'));
    formData.set('signature', signature);
    // Kembalikan data form.
    return {
        host: `http://${client.options.bucket}.oss-${client.options.region}.aliyuncs.com`, 
        policy: Buffer.from(policy2Str(policy), 'utf8').toString('base64'),
        x_oss_signature_version: 'OSS4-HMAC-SHA256',
        x_oss_credential: credential,
        x_oss_date: formattedDate,
        signature: signature,
        dir: 'user-dir', // Awalan (direktori) untuk objek yang akan diunggah ke OSS.
        security_token: client.options.stsToken
    };
};
app.get('/get_post_signature_for_oss_upload', async (req, res) => {
    try {
        const result = await GenerateSignature();
        res.json(result); // Kembalikan data signature yang dihasilkan.
    } catch (error) {
        console.error('Error generating signature:', error);
        res.status(500).send('Error generating signature');
    }
});
app.listen(PORT, () => {
    console.log(`Server is running on http://127.0.0.1:${PORT}`); // Jika Anda perlu mendengarkan alamat lain seperti 0.0.0.0, Anda harus menambahkan mekanisme autentikasi sisi server.
});

Go

Jalankan perintah berikut untuk menginstal dependensi.

go get -u github.com/aliyun/credentials-go
go mod tidy

Kode contoh berikut menunjukkan cara mendapatkan kredensial akses temporary (token STS), menyusun kebijakan unggahan, dan menghitung signature POST di server.

package main
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/base64"
    "encoding/hex"
    "encoding/json"
    "fmt"
    "io"
    "hash"
    "log"
    "net/http"
    "os"
    "time"
    "github.com/aliyun/credentials-go/credentials"
)
// Definisikan variabel global.
var (
    region     string
    bucketName string
    product    = "oss"
)
// Struct PolicyToken menyimpan data form yang dihasilkan.
type PolicyToken struct {
    Policy           string `json:"policy"`
    SecurityToken    string `json:"security_token"`
    SignatureVersion string `json:"x_oss_signature_version"`
    Credential       string `json:"x_oss_credential"`
    Date             string `json:"x_oss_date"`
    Signature        string `json:"signature"`
    Host             string `json:"host"` 
    Dir              string `json:"dir"` 
}
func main() {
    // Definisikan string alamat IP dan port default.
    strIPPort := ":8000"
    if len(os.Args) == 3 {
    strIPPort = fmt.Sprintf("%s:%s", os.Args[1], os.Args[2])
    } else if len(os.Args) != 1 {
    fmt.Println("Usage   : go run test1.go                ")
    fmt.Println("Usage   : go run test1.go ip port        ")
    fmt.Println("")
    os.Exit(0)
    }
    // Cetak alamat dan port tempat server berjalan.
    fmt.Printf("server is running on %s \n", strIPPort)
    // Daftarkan fungsi untuk menangani permintaan path root.
    http.HandleFunc("/", handlerRequest)
    // Daftarkan fungsi untuk menangani permintaan pembuatan signature.
    http.HandleFunc("/get_post_signature_for_oss_upload", handleGetPostSignature)
    // Mulai server HTTP.
    err := http.ListenAndServe(strIPPort, nil)
    if err != nil {
    strError := fmt.Sprintf("http.ListenAndServe failed : %s \n", err.Error())
    panic(strError)
    }
}
// Fungsi handlerRequest menangani permintaan path root.
func handlerRequest(w http.ResponseWriter, r *http.Request) {
    if r.Method == "GET" {
    http.ServeFile(w, r, "templates/index.html")
    return
    }
    http.NotFound(w, r)
}
// Fungsi handleGetPostSignature menangani permintaan pembuatan signature.
func handleGetPostSignature(w http.ResponseWriter, r *http.Request) {
    if r.Method == "GET" {
    response := getPolicyToken()
    w.Header().Set("Content-Type", "application/json")
    w.Header().Set("Access-Control-Allow-Origin", "*") // Izinkan permintaan lintas asal.
    w.Write([]byte(response))
    return
    }
    http.NotFound(w, r)
}
// Fungsi getPolicyToken menghasilkan signature dan kredensial yang diperlukan untuk unggahan OSS.
func getPolicyToken() string {
    // Tetapkan wilayah bucket.
    region = "cn-hangzhou"
    // Ganti dengan nama bucket Anda.
    bucketName = "examplebucket"
    // Tetapkan alamat unggahan OSS.
    host := fmt.Sprintf("https://%s.oss-%s.aliyuncs.com", bucketName, region)
    // Tetapkan direktori unggahan.
    dir := "user-dir"
    config := new(credentials.Config).
    SetType("ram_role_arn").
    SetAccessKeyId(os.Getenv("OSS_ACCESS_KEY_ID")).
    SetAccessKeySecret(os.Getenv("OSS_ACCESS_KEY_SECRET")).
    SetRoleArn("OSS_STS_ROLE_ARN").
    SetRoleSessionName("Role_Session_Name").
    SetPolicy("").
    SetRoleSessionExpiration(3600)
    // Buat penyedia kredensial berdasarkan konfigurasi.
    provider, err := credentials.NewCredential(config)
    if err != nil {
    log.Fatalf("NewCredential fail, err:%v", err)
    }
    // Dapatkan kredensial dari penyedia kredensial.
    cred, err := provider.GetCredential()
    if err != nil {
    log.Fatalf("GetCredential fail, err:%v", err)
    }
    // Susun kebijakan.
    utcTime := time.Now().UTC()
    date := utcTime.Format("20060102")
    expiration := utcTime.Add(1 * time.Hour)
    policyMap := map[string]any{
    "expiration": expiration.Format("2006-01-02T15:04:05.000Z"),
    "conditions": []any{
    map[string]string{"bucket": bucketName},
    map[string]string{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
    map[string]string{"x-oss-credential": fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product)},
    map[string]string{"x-oss-date": utcTime.Format("20060102T150405Z")},
    map[string]string{"x-oss-security-token": *cred.SecurityToken},
    },
    }
    // Konversi kebijakan ke format JSON.
    policy, err := json.Marshal(policyMap)
    if err != nil {
    log.Fatalf("json.Marshal fail, err:%v", err)
    }
    // Susun string untuk ditandatangani.
    stringToSign := base64.StdEncoding.EncodeToString([]byte(policy))
    hmacHash := func() hash.Hash { return sha256.New() }
        // Susun kunci penandatanganan.
    signingKey := "aliyun_v4" + *cred.AccessKeySecret
    h1 := hmac.New(hmacHash, []byte(signingKey))
    io.WriteString(h1, date)
    h1Key := h1.Sum(nil)
    h2 := hmac.New(hmacHash, h1Key)
    io.WriteString(h2, region)
    h2Key := h2.Sum(nil)
    h3 := hmac.New(hmacHash, h2Key)
    io.WriteString(h3, product)
    h3Key := h3.Sum(nil)
    h4 := hmac.New(hmacHash, h3Key)
    io.WriteString(h4, "aliyun_v4_request")
    h4Key := h4.Sum(nil)
    // Hasilkan signature.
    h := hmac.New(hmacHash, h4Key)
    io.WriteString(h, stringToSign)
    signature := hex.EncodeToString(h.Sum(nil))
    // Susun form yang akan dikembalikan ke klien.
    policyToken := PolicyToken{
    Policy:           stringToSign,
    SecurityToken:    *cred.SecurityToken,
    SignatureVersion: "OSS4-HMAC-SHA256",
    Credential:       fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product),
    Date:             utcTime.UTC().Format("20060102T150405Z"),
    Signature:        signature,
    Host:             host, // Alamat unggahan OSS.
    Dir:              dir,  // Direktori unggahan.
    }
    response, err := json.Marshal(policyToken)
    if err != nil {
    fmt.Println("json err:", err)
    }
    return string(response)
}

PHP

Jalankan perintah berikut untuk menginstal dependensi.

composer install

Kode contoh berikut menunjukkan cara mendapatkan kredensial akses temporary (token STS), menyusun kebijakan unggahan, dan menghitung signature POST di server.

<?php
// Impor SDK Alibaba Cloud.
require_once __DIR__ . '/vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\Sts\Sts;
// Nonaktifkan tampilan error.
ini_set('display_errors', '0');
$bucket = 'examplebucket'; // Ganti dengan nama bucket Anda.
$region_id = 'cn-hangzhou'; // Ganti dengan wilayah bucket Anda.
$host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'; // Ganti dengan nama domain bucket Anda.
$expire_time = 3600; // Waktu kedaluwarsa dalam detik.
$upload_dir = 'user-dir'; // Awalan (direktori) untuk objek yang diunggah.
// Hitung HMAC-SHA256.
function hmacsha256($key, $data) {
    return hash_hmac('sha256', $data, $key, true);
}
// Tangani permintaan untuk mendapatkan signature POST.
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/get_post_signature_for_oss_upload') {
    AlibabaCloud::accessKeyClient(getenv('OSS_ACCESS_KEY_ID'), getenv('OSS_ACCESS_KEY_SECRET'))
        ->regionId('cn-hangzhou')
        ->asDefaultClient();
    // Buat permintaan STS.
    $request = Sts::v20150401()->assumeRole();
    // Lakukan permintaan STS dan dapatkan hasilnya.
    // Tetapkan <YOUR_ROLE_SESSION_NAME> ke nama sesi kustom, seperti oss-role-session.
    // Ganti <YOUR_ROLE_ARN> dengan ARN peran RAM yang memiliki izin untuk mengunggah file ke bucket OSS yang ditentukan.
    $result = $request
        ->withRoleSessionName('oss-role-session')
        ->withDurationSeconds(3600)
        ->withRoleArn(getenv('OSS_STS_ROLE_ARN'))
        ->request();
    // Dapatkan informasi kredensial dari hasil permintaan STS.
    $tokenData = $result->get('Credentials');
    // Susun data JSON untuk dikembalikan.
    $tempAccessKeyId = $tokenData['AccessKeyId'];
    $tempAccessKeySecret = $tokenData['AccessKeySecret'];
    $securityToken = $tokenData['SecurityToken'];
    $now = time();
    $dtObj = gmdate('Ymd\THis\Z', $now);
    $dtObj1 = gmdate('Ymd', $now);
    $dtObjPlus3h = gmdate('Y-m-d\TH:i:s.u\Z', strtotime('+3 hours', $now));
    // Susun kebijakan.
    $policy = [
        "expiration" => $dtObjPlus3h,
        "conditions" => [
            ["x-oss-signature-version" => "OSS4-HMAC-SHA256"],
            ["x-oss-credential" => "{$tempAccessKeyId}/{$dtObj1}/cn-hangzhou/oss/aliyun_v4_request"],
            ["x-oss-security-token" => $securityToken],
            ["x-oss-date" => $dtObj],
        ]
    ];
    $policyStr = json_encode($policy);
    // Susun string untuk ditandatangani.
    $stringToSign = base64_encode($policyStr);
    // Hitung kunci penandatanganan.
    $dateKey = hmacsha256(('aliyun_v4' . $tempAccessKeySecret), $dtObj1);
    $dateRegionKey = hmacsha256($dateKey, 'cn-hangzhou');
    $dateRegionServiceKey = hmacsha256($dateRegionKey, 'oss');
    $signingKey = hmacsha256($dateRegionServiceKey, 'aliyun_v4_request');
    // Hitung signature.
    $result = hmacsha256($signingKey, $stringToSign);
    $signature = bin2hex($result);
    // Kembalikan data signature.
    $responseData = [
        'policy' => $stringToSign,
        'x_oss_signature_version' => "OSS4-HMAC-SHA256",
        'x_oss_credential' => "{$tempAccessKeyId}/{$dtObj1}/cn-hangzhou/oss/aliyun_v4_request",
        'x_oss_date' => $dtObj,
        'signature' => $signature,
        'host' => $host,
        'dir' => $upload_dir,
        'security_token' => $securityToken
    ];
    header('Content-Type: application/json');
    echo json_encode($responseData);
    exit;
}
// Rute halaman utama.
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/') {
    echo file_get_contents(__DIR__ . '/public/index.html');
    exit;
}
// Rute lainnya.
http_response_code(404);
echo json_encode(['message' => 'Not Found']);
exit;
?>

Langkah 3: Konfigurasikan klien web

Unggah form sisi klien

Setelah klien web menerima informasi yang diperlukan dari server aplikasi, klien tersebut membangun permintaan formulir HTML. Permintaan ini berkomunikasi langsung dengan OSS untuk mengunggah file.

Klien web: Respons contoh

Server aplikasi mengembalikan token STS dan kebijakan unggahan ke klien web.

{
    "dir": "user-dirs",
    "host": "http://examplebucket.oss-cn-hangzhou.aliyuncs.com",
    "policy": "eyJl****",
    "security_token": "CAIS****",
    "signature": "9103****",
    "x_oss_credential": "STS.NSpW****/20241127/cn-hangzhou/oss/aliyun_v4_request",
    "x_oss_date": "20241127T060941Z",
    "x_oss_signature_version": "OSS4-HMAC-SHA256"
}

Tabel berikut menjelaskan setiap field dalam badan respons.

Parameter

Deskripsi

dir

Menentukan awalan nama objek yang diperlukan untuk unggahan.

host

Nama domain bucket tujuan.

policy

Kebijakan yang digunakan untuk unggahan form berbasis browser. Untuk informasi selengkapnya, lihat Post Policy.

security_token

Kredensial temporary yang digunakan untuk otentikasi, disediakan oleh STS.

signature

Signature yang dihasilkan dari kebijakan. Untuk informasi selengkapnya, lihat Post Signature.

x_oss_credential

Menentukan set parameter yang digunakan untuk menurunkan kunci penandatanganan.

x_oss_date

Waktu permintaan dalam format ISO 8601, misalnya, 20231203T121212Z.

x_oss_signature_version

Versi dan algoritma signature. Nilainya tetap OSS4-HMAC-SHA256.

  • Permintaan form mencakup konten file dan parameter yang dikembalikan oleh server aplikasi.

  • Dengan permintaan ini, klien web berkomunikasi langsung dengan OSS untuk mengunggah file.

Catatan
  • Kecuali field form file, semua field form lainnya, termasuk key, tidak boleh melebihi 8 KB.

  • Secara default, unggahan berbasis web menimpa objek dengan nama yang sama. Untuk mencegah objek ditimpa, tambahkan field form x-oss-forbid-overwrite ke permintaan dan atur nilainya ke true. Jika objek dengan nama yang sama sudah ada di OSS, unggahan gagal dan OSS mengembalikan error FileAlreadyExists.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hasilkan signature di server untuk mengunggah file ke OSS</title>
</head>
<body>
<div class="container">
    <form>
        <div class="mb-3">
            <label for="file" class="form-label">Pilih file:</label>
            <input type="file" class="form-control" id="file" name="file" required />
        </div>
        <button type="submit" class="btn btn-primary">Unggah</button>
    </form>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
    const form = document.querySelector("form");
    const fileInput = document.querySelector("#file");
    form.addEventListener("submit", (event) => {
        event.preventDefault();
        const file = fileInput.files[0];
        if (!file) {
            alert('Silakan pilih file untuk diunggah.');
            return;
        }
        const filename = file.name;
        fetch("/get_post_signature_for_oss_upload", { method: "GET" })
            .then((response) => {
                if (!response.ok) {
                    throw new Error("Gagal mendapatkan signature");
                }
                return response.json();
            })
            .then((data) => {
                let formData = new FormData();
                formData.append("success_action_status", "200");
                formData.append("policy", data.policy);
                formData.append("x-oss-signature", data.signature);
                formData.append("x-oss-signature-version", "OSS4-HMAC-SHA256");
                formData.append("x-oss-credential", data.x_oss_credential);
                formData.append("x-oss-date", data.x_oss_date);
                formData.append("key", data.dir + file.name); // Nama objek
                formData.append("x-oss-security-token", data.security_token);
                formData.append("file", file); // file harus menjadi field form terakhir
                return fetch(data.host, { 
                    method: "POST",
                    body: formData
                });
            })
            .then((response) => {
                if (response.ok) {
                    console.log("Unggahan berhasil.");
                    alert("File berhasil diunggah.");
                } else {
                    console.log("Unggahan gagal", response);
                    alert("Unggahan gagal. Silakan coba lagi nanti.");
                }
            })
            .catch((error) => {
                console.error("Terjadi kesalahan:", error);
            });
    });
});
</script>
</body>
</html>
  • Formulir HTML berisi input file dan tombol submit.

  • Saat formulir dikirim, kode JavaScript mencegah pengiriman default dan mengirim permintaan AJAX ke server aplikasi untuk informasi signature yang diperlukan.

  • Setelah menerima informasi signature, kode tersebut membuat objek FormData dengan field form yang diperlukan.

  • Kemudian, kode tersebut menggunakan metode fetch untuk mengirim permintaan POST ke URL OSS untuk mengunggah file.

Jika unggahan berhasil, pesan "File berhasil diunggah." ditampilkan. Jika unggahan gagal, pesan error ditampilkan.

Verifikasi

Setelah penerapan, akses server aplikasi Anda untuk menguji fitur unggah langsung dengan URL yang ditandatangani.

  1. Di browser, akses server aplikasi Anda. Klik Select File, pilih file, lalu unggah.

  2. Di halaman Buckets, buka bucket yang Anda buat dan verifikasi bahwa objek yang diunggah ada.

Konfigurasi yang direkomendasikan

Kebijakan unggah file

Anda dapat memodifikasi kebijakan dalam kode Anda untuk menetapkan izin dan batasan unggahan file ke OSS dari formulir HTML. Kebijakan berformat JSON memungkinkan Anda membatasi unggahan dengan menetapkan parameter seperti nama bucket yang diizinkan, awalan objek, waktu kedaluwarsa, metode HTTP yang diizinkan, batas ukuran konten, dan tipe konten.

{
  "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/jpeg", "image/png"]],
    ["not-in", "$cache-control", ["no-cache"]]
  ]
}

Untuk informasi selengkapnya tentang parameter kebijakan, lihat Post Policy.

Penandatanganan sisi server dan callback unggahan

Untuk menerima metadata tentang file yang diunggah, seperti nama file dan ukurannya, konfigurasikan callback unggahan. Setelah file diunggah, OSS mengirim informasi file tersebut ke server aplikasi Anda. Untuk informasi selengkapnya, lihat Penandatanganan sisi server dan unggah langsung dengan callback unggahan.

Batasi origin CORS

Untuk kesederhanaan, origin yang diizinkan sebelumnya diatur ke karakter wildcard *. Sebagai praktik keamanan terbaik, Anda harus mengganti wildcard tersebut dengan URL spesifik server aplikasi Anda. Hal ini memastikan bahwa hanya permintaan lintas asal dari server Anda yang diotorisasi.

Parameter

Nilai contoh

Origin

http://<your_application_server_address>

Allowed Methods

POST, PUT, GET

Allowed Headers

*

Bersihkan sumber daya

Dalam solusi ini, Anda membuat satu instance ECS, satu bucket OSS, satu pengguna RAM, dan satu peran RAM. Setelah selesai menguji, bersihkan sumber daya ini untuk menghindari biaya berkelanjutan atau risiko keamanan.

Lepaskan instance ECS

Jika Anda tidak lagi memerlukan instance tersebut, lepaskan. Setelah melepaskan instance, penagihan berhenti dan Anda tidak dapat memulihkan datanya.

  1. Buka halaman Instances di Konsol ECS. Temukan instance ECS target berdasarkan wilayah dan ID instance, lalu klik image di kolom Actions.

  2. Pilih Release. Di menu yang muncul, klik Release.

  3. Konfirmasi detail instance, pilih Release Now, lalu klik Next.

  4. Tinjau sumber daya terkait yang akan dilepaskan, akui risiko data terkait, lalu klik Confirm.

Catatan
  • Disk sistem dan Alamat IP publik yang ditetapkan dilepaskan bersama instance.

  • Grup keamanan, vSwitch, dan VPC tidak dilepaskan bersama instance. Sumber daya ini gratis, tetapi Anda dapat menghapusnya jika tidak lagi diperlukan.

  • EIP tidak dilepaskan bersama instance dan terus dikenai biaya. Hapus secara terpisah jika tidak lagi diperlukan.

Hapus bucket OSS

  1. Login ke Konsol OSS.

  2. Klik Buckets, lalu klik nama bucket OSS target.

  3. Hapus semua objek dalam bucket.

  4. Di panel navigasi kiri, klik Delete Bucket dan ikuti petunjuk di layar.

Hapus pengguna RAM

  1. Login ke Konsol RAM sebagai pengguna RAM dengan hak admin.

  2. Di panel navigasi kiri, pilih .

  3. Di halaman Users, temukan pengguna RAM target dan klik Delete di kolom Actions.

    Atau, pilih beberapa pengguna RAM dan klik Delete User di bawah daftar untuk memindahkannya ke Recycle Bin.

  4. Di kotak dialog Delete User, tinjau dengan cermat dampak penghapusan, masukkan nama pengguna RAM target, lalu klik Move to Recycle Bin.

Hapus peran RAM

  1. Login ke Konsol RAM sebagai pengguna RAM dengan hak admin.

  2. Di panel navigasi kiri, pilih .

  3. Di halaman Roles, temukan peran RAM target dan klik Delete Role di kolom Actions.

  4. Di kotak dialog Delete Role, masukkan nama peran RAM dan klik Delete Role.

    Catatan

    Jika peran RAM memiliki kebijakan yang dilampirkan, menghapus peran tersebut juga melepas kebijakan tersebut.

FAQ

Unggahan multipart dan yang dapat dilanjutkan

Solusi ini menggunakan unggahan form dan tidak mendukung unggahan multipart atau yang dapat dilanjutkan. Untuk menggunakan metode ini, lihat Unggah yang dapat dilanjutkan dan Unggahan multipart.

Cegah penimpaan file

Tetapkan parameter x-oss-forbid-overwrite ke true di field form unggahan. Contohnya:

formData.append('x-oss-forbid-overwrite', 'true');