All Products
Search
Document Center

Object Storage Service:Penandatanganan sisi server untuk unggah langsung

Last Updated:Jun 21, 2026

Operasi PostObject memungkinkan Anda mengunggah file langsung dari klien web ke Object Storage Service (OSS). Operasi ini menggunakan tanda tangan 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 sementara 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) pada bucket tersebut agar mengizinkan permintaan lintas asal dari klien web.

  2. Konfigurasikan server: Panggil Security Token Service (STS) untuk mendapatkan kredensial akses sementara. Gunakan kredensial ini beserta kebijakan unggah sisi server untuk menghasilkan tanda tangan. Kebijakan mencakup parameter seperti nama bucket, jalur direktori, dan waktu kedaluwarsa. Tanda tangan ini memberi otorisasi kepada pengguna untuk mengunggah file dalam periode tertentu.

  3. Konfigurasikan klien web: Susun permintaan formulir HTML dan gunakan tanda tangan 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. Di panel navigasi sebelah kiri, klik Buckets, lalu klik Create Bucket.

  3. Di 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. Di halaman Buckets, klik bucket target.

  2. Di halaman CORS, klik Create Rule.

  3. Di 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 ke 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.

    image

    Di 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.

    Contoh konfigurasi vSwitch: 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.

    image

  1. Konfigurasikan penyimpanan

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

    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. Sebagai alternatif, Anda dapat mengaitkan Elastic IP Address (EIP) ke instans setelah membuatnya. Untuk informasi selengkapnya, lihat Associate an EIP with a cloud resource.

    Catatan
    • Jika alamat IP publik tidak ditetapkan, Anda tidak dapat menggunakan SSH atau Protokol Desktop Jarak Jauh (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 Public bandwidth billing.

    Atur Peak bandwidth menjadi 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 untuk aplikasi yang berjalan pada instance ECS.

    • Secara default, grup keamanan yang dibuat di sini mencakup aturan yang mengatur sumber 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 menyarankan agar Anda kemudian membatasi sumber ke rentang IP tertentu. Untuk informasi selengkapnya, lihat Modify a security group rule.

    Di 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 menyarankan agar Anda menggunakan ecs-user sebagai nama login.

      Catatan

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

      Di 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 di daftar instance.

    • Region: Digunakan untuk menemukan instance di daftar instance.

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

Langkah 2: Hubungkan ke instance ECS

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

  2. Di kotak dialog Remote connection, klik Sign in now di samping Workbench.

  3. Di 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 dijadikan kredensial jangka panjang bagi server aplikasi Anda.

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

  2. Di panel navigasi sebelah kiri, pilih Identities > Users.

  3. Klik Create User.

  4. Masukkan Logon Name dan Display Name.

  5. Di 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. Di 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 sementara dengan mengasumsikan peran RAM.

  1. Di panel navigasi sebelah kiri, pilih Identities > Users.

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

  3. Di 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 sementara, 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. Di panel navigasi sebelah 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. Di 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. Di panel navigasi sebelah kiri, pilih Permissions > Policies.

  2. Klik Create Policy.

  3. Di 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. Di kotak dialog Create Policy, masukkan Policy Name dan klik OK.

Langkah 5: Berikan izin kepada peran RAM

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

  1. Di panel navigasi sebelah kiri, pilih Identities > Roles.

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

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

  4. Klik OK.

Penandatanganan sisi server

Catatan

Kami menyarankan 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 mengatur 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 diatur.

    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 diatur.

      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 diatur.

      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 diatur.

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

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

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 sementara dan menghitung tanda tangan 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";
    // Atur 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 Kunci Akses merupakan risiko keamanan dan tidak disarankan. 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 diatur di lingkungan runtime kode Anda.
                .setAccessKeyId(System.getenv("OSS_ACCESS_KEY_ID"))
                // Wajib. Pastikan variabel lingkungan OSS_ACCESS_KEY_SECRET diatur di lingkungan runtime kode Anda.
                .setAccessKeySecret(System.getenv("OSS_ACCESS_KEY_SECRET"));
        // Untuk informasi selengkapnya tentang titik akhir, lihat https://api.aliyun.com/product/Sts.
        config.endpoint = "sts.cn-hangzhou.aliyuncs.com";
        return new com.aliyun.sts20150401.Client(config);
    }
    /**
     * Dapatkan kredensial sementara 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 diatur 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 yang akan 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 tanda tangan.
        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 tanda tangan 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 sementara (token STS), menyusun kebijakan unggahan, dan menghitung tanda tangan 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 menjadi 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 hasilkan 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 sementara (token STS), menyusun kebijakan unggahan, dan menghitung tanda tangan 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.
// Atur 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 sementara.
    const result = await sts.assumeRole(process.env.OSS_STS_ROLE_ARN, '', '3600', 'yourRoleSessionName'); // Dapatkan ARN peran RAM dari variabel lingkungan. Kredensial akses sementara berlaku selama 3.600 detik, dan nama sesi peran adalah nilai kustom, seperti yourRoleSessionName.
    // Ekstrak AccessKeyId, AccessKeySecret, dan SecurityToken dari kredensial akses sementara.
    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 formulir.
    const formData = new Map();
    // Atur waktu kedaluwarsa tanda tangan menjadi 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 atur data formulir.
    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 formulir.
    if (client.options.stsToken) {
        policy.conditions.push({ 'x-oss-security-token': client.options.stsToken });
        formData.set('security_token', client.options.stsToken);
    }
    // Hasilkan tanda tangan dan atur data formulir.
    const signature = client.signPostObjectPolicyV4(policy, date);
    formData.set('policy', Buffer.from(policy2Str(policy), 'utf8').toString('base64'));
    formData.set('signature', signature);
    // Kembalikan data formulir.
    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 tanda tangan 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 sementara (token STS), menyusun kebijakan unggahan, dan menghitung tanda tangan 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"
)
// Struktur PolicyToken menyimpan data formulir 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 jalur root.
    http.HandleFunc("/", handlerRequest)
    // Daftarkan fungsi untuk menangani permintaan pembuatan tanda tangan.
    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 jalur 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 tanda tangan.
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 tanda tangan dan kredensial yang diperlukan untuk unggahan OSS.
func getPolicyToken() string {
    // Atur wilayah bucket.
    region = "cn-hangzhou"
    // Ganti dengan nama bucket Anda.
    bucketName = "examplebucket"
    // Atur alamat unggahan OSS.
    host := fmt.Sprintf("https://%s.oss-%s.aliyuncs.com", bucketName, region)
    // Atur 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 yang akan 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 tanda tangan.
    h := hmac.New(hmacHash, h4Key)
    io.WriteString(h, stringToSign)
    signature := hex.EncodeToString(h.Sum(nil))
    // Susun formulir 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 sementara (token STS), menyusun kebijakan unggahan, dan menghitung tanda tangan 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 tanda tangan 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();
    // Mulai permintaan STS dan dapatkan hasilnya.
    // Atur <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 yang akan 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 yang akan 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 tanda tangan.
    $result = hmacsha256($signingKey, $stringToSign);
    $signature = bin2hex($result);
    // Kembalikan data tanda tangan.
    $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 formulir 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 bidang 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 formulir berbasis browser. Untuk informasi selengkapnya, lihat Post Policy.

security_token

Kredensial sementara yang digunakan untuk otentikasi, disediakan oleh STS.

signature

Tanda tangan 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 tanda tangan. Nilainya tetap OSS4-HMAC-SHA256.

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

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

Catatan
  • Kecuali bidang formulir file, semua bidang formulir lainnya, termasuk key, tidak boleh melebihi 8 KB.

  • Secara default, unggahan berbasis web menimpa objek dengan nama yang sama. Untuk mencegah penimpaan objek, tambahkan bidang formulir 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 tanda tangan 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 tanda tangan");
                }
                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 bidang formulir 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 tanda tangan yang diperlukan.

  • Setelah menerima informasi tanda tangan, kode membuat objek FormData dengan bidang formulir yang diperlukan.

  • Kemudian, kode tersebut menggunakan metode fetch untuk mengirim permintaan POST ke URL OSS guna 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 mengatur izin dan batasan unggahan file ke OSS dari formulir HTML. Kebijakan berformat JSON memungkinkan Anda membatasi unggahan dengan mengatur 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 Server-side signing and direct upload with an upload callback.

Batasi asal CORS

Untuk kesederhanaan, asal 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 di bucket tersebut.

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

Hapus pengguna RAM

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

  2. Di panel navigasi sebelah 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 istimewa admin.

  2. Di panel navigasi sebelah 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 formulir dan tidak mendukung unggahan multipart atau yang dapat dilanjutkan. Untuk menggunakan metode ini, lihat Resumable upload dan Multipart upload.

Cegah penimpaan file

Atur parameter x-oss-forbid-overwrite ke true di bidang formulir unggahan. Contohnya:

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