Unggah objek langsung dari klien web ke OSS menggunakan operasi PostObject dengan tanda tangan yang dihasilkan oleh server. Pendekatan ini mendukung callback unggahan dan kebijakan untuk mengontrol unggahan.
Ikhtisar solusi
Alur kerja ini terdiri dari tiga langkah:
Proses ini menggunakan kredensial akses sementara untuk menghindari pengeksposan pasangan AccessKey server aplikasi.
-
Konfigurasikan OSS: Buat bucket dan konfigurasikan aturan Berbagi Sumber Daya Lintas Domain (CORS) untuk mengizinkan permintaan lintas asal dari klien web.
-
Konfigurasikan server: Hasilkan tanda tangan berdurasi terbatas menggunakan kredensial akses dan kebijakan dengan kondisi seperti nama bucket, path direktori, dan waktu kedaluwarsa.
-
Konfigurasikan klien web: Buat formulir HTML untuk mengunggah objek langsung ke OSS. OSS mengurai pengaturan callback dan mengirim permintaan POST callback ke server aplikasi.
Proyek contoh
Prosedur
Langkah 1: Konfigurasikan OSS
Langkah 1: Buat bucket
Buat bucket untuk menyimpan file yang diunggah dari klien web.
-
Login ke Konsol OSS.
-
Di panel navigasi kiri, klik Buckets, lalu klik Create Bucket.
-
Di panel Create Bucket, pilih Quick Create dan konfigurasikan parameter berikut.
Parameter
Nilai contoh
Bucket Name
web-direct-upload-callback
Region
China (Hangzhou)
-
Klik Create.
Langkah 2: Konfigurasikan aturan CORS
Konfigurasikan aturan CORS untuk bucket OSS Anda.
-
Buka halaman Buckets dan klik nama bucket target.
-
Di halaman CORS, klik Create Rule.
-
Di panel Create Rule, konfigurasikan aturan CORS sebagai berikut.
Parameter
Nilai contoh
Origin
*
Allowed Methods
POST, PUT, GET
Allowed Headers
*
-
Klik OK.
Langkah 2: Konfigurasikan server
Jika Anda sudah memiliki server, lewati persiapan dan lanjutkan ke Izin pengguna.
Buat instance ECS
Langkah 1: Buat instance ECS
Buka halaman Custom Launch dan konfigurasikan resource berikut.
-
Pilih wilayah dan metode penagihan
-
Pilih metode penagihan. Topik ini menggunakan pay-as-you-go.
-
Pilih wilayah yang dekat dengan pengguna akhir Anda. Topik ini menggunakan China (Hangzhou).
Di bagian Billing method, pilih pay-as-you-go.
-
-
Buat VPC dan vSwitch
Setelah membuat VPC dan vSwitch, kembali ke halaman pembuatan instance ECS, refresh, lalu pilih keduanya.
CatatanAnda dapat membuat vSwitch saat membuat VPC.
Di halaman Create Virtual Private Cloud, atur Name menjadi
ProjectA-VPC. Untuk IPv4 CIDR block, pilih Enter IPv4 CIDR Block Manually dan masukkan192.168.0.0/16. Untuk IPv6 CIDR block, pilih No IPv6.Di bagian vSwitch, atur Name menjadi
ProjectA-vSwitch. Untuk Availability Zone, pilih Hangzhou Zone H. Atur IPv4 CIDR block menjadi192.168.10.0/24, lalu klik OK.
-
Pilih tipe instans dan gambar
Tutorial ini menggunakan tipe instans
ecs.e-c1m1.largedan gambar publikAlibaba Cloud Linux 3.2104 LTS 64-bit.Di bagian Instance type, pada tab All generations, cari dan pilih tipe instans
ecs.e-c1m1.large. Di bagian Image, pada tab Public image, pilih Alibaba Cloud Linux sebagai sistem operasi dan 3.2104 LTS 64-bit sebagai versi.
-
Konfigurasikan penyimpanan
Tutorial ini hanya memerlukan disk sistem. Tidak diperlukan disk data.
Untuk disk sistem, pilih ESSD. Atur kapasitas menjadi 40 GiB dan tingkat kinerja menjadi PL0 (IOPS maksimum per disk: 10.000). Pilih kotak centang Release with instance.
-
Tetapkan alamat IP publik
Instans ini memerlukan akses internet. Tutorial ini menetapkan alamat IP publik selama pembuatan. Sebagai alternatif, Asosiasikan EIP dengan sumber daya cloud setelah pembuatan.
Catatan-
Tanpa alamat IP publik, Anda tidak dapat menghubungkan instans melalui internet atau memverifikasi penerapan layanan web.
-
Tutorial ini menggunakan penagihan pay-by-traffic, yang hanya menagih data arah keluar. Penagihan bandwidth publik.
Atur Peak bandwidth menjadi 5 Mbps.
-
-
Buat grup keamanan
Grup keamanan mengontrol lalu lintas inbound dan outbound untuk instance ECS Anda. Buka port berikut untuk mengizinkan lalu lintas inbound.
Port range: SSH (22), RDP (3389), HTTP (80), dan HTTPS (443).
Catatan-
Parameter Port range menentukan port yang diperlukan oleh aplikasi yang berjalan di instance ECS.
-
Secara default, grup keamanan mengizinkan lalu lintas dari semua alamat IP (0.0.0.0/0). Setelah pembuatan, batasi lalu lintas ke rentang IP tertentu. Ubah aturan grup keamanan.
Untuk Security group type, pilih Basic security group.
-
-
Buat pasangan kunci
-
Setelah membuat pasangan kunci, unduh dan simpan kunci privat ke menghubungkan instance ECS nanti. Kembali ke halaman pembuatan instans, refresh, lalu pilih pasangan kunci tersebut.
-
Pengguna
rootmemiliki hak istimewa penuh sistem. Login sebagairootmenimbulkan risiko keamanan. Gunakanecs-usersebagai username login.CatatanFile kunci privat diunduh secara otomatis. Simpan file
.pemdari riwayat unduhan browser Anda.Klik tautan Create a key pair untuk membuat pasangan kunci baru. Kemudian, di daftar drop-down Key pair, pilih pasangan kunci yang baru saja Anda buat, misalnya
ecs-test.
-
-
Buat dan lihat instance ECS
Klik Create Order lalu klik Console untuk melihat instance ECS baru Anda. Catat informasi berikut:
-
Instance ID: Digunakan untuk menemukan instans di daftar instans.
-
Region: Digunakan untuk menemukan instans di daftar instans.
-
Public IP address: Digunakan untuk mengakses dan memverifikasi layanan web yang diterapkan.
Di daftar instans Konsol ECS, Anda dapat menemukan Instance ID, Region, dan Public IP address di kolom masing-masing.
-
Langkah 2: Hubungkan ke instance ECS
-
Di halaman Instances Konsol ECS, temukan instans yang Anda buat berdasarkan wilayah dan ID-nya. Di kolom Actions, klik Connect.
-
Di kotak dialog Remote connection, di bawah opsi Workbench, klik Sign in now.
-
Di kotak dialog Log on to instance, atur Connection method menjadi Terminal dan Authentication method menjadi SSH key-based authentication. Masukkan atau unggah file kunci privat yang Anda unduh saat membuat pasangan kunci, lalu klik Log In. Anda sekarang telah login ke instance ECS sebagai
ecs-user.CatatanPeriksa riwayat unduhan browser Anda untuk file kunci privat
.pem. -
Output login berhasil:
Welcome to Alibaba Cloud Elastic Compute Service ! Last login: Sun Sep 29 15:35:22 2024 from xxx [ecs-user@ixxx ~]$
Izin pengguna
Buat pengguna RAM dan berikan izin yang diperlukan sebelum penerapan untuk mencegah kegagalan unggahan.
Langkah 1: Buat pengguna RAM
Buat pengguna RAM dan peroleh AccessKey-nya sebagai kredensial jangka panjang untuk aplikasi server.
-
Login ke Konsol RAM menggunakan Akun Alibaba Cloud Anda atau sebagai administrator RAM.
-
Di panel navigasi kiri, pilih Identities > Users.
-
Klik Create User.
-
Masukkan Logon Name dan Display Name.
-
Di bagian Access Mode, pilih Programmatic access, lalu klik OK.
Rahasia AccessKey untuk pengguna RAM hanya ditampilkan sekali, saat pembuatan, dan tidak dapat diambil kembali. Pastikan untuk menyimpannya dengan aman.
-
Klik Copy di kolom Actions untuk menyimpan AccessKey (ID AccessKey dan Rahasia AccessKey).
Langkah 2: Berikan izin AssumeRole
Berikan izin kepada pengguna RAM untuk memanggil operasi STS AssumeRole guna memperoleh kredensial sementara.
-
Di panel navigasi kiri, pilih Identities > Users.
-
Di halaman Users, temukan pengguna RAM target, lalu klik Add Permissions di kolom Actions.
-
Di halaman Add Permissions, pilih kebijakan sistem AliyunSTSAssumeRoleAccess.
CatatanKebijakan AliyunSTSAssumeRoleAccess memberikan izin untuk memanggil operasi STS AssumeRole. Ini terpisah dari izin akses OSS yang diberikan melalui kredensial sementara.
Atur Resource Scope menjadi Account Level, lalu klik OK.
-
Klik Confirm Authorization.
Langkah 3: Buat peran RAM
Buat peran RAM untuk Akun Alibaba Cloud Anda dan peroleh Nama Sumber Daya Alibaba Cloud (ARN)-nya.
-
Di panel navigasi kiri, pilih Identities > Roles.
-
Klik Create Role. Untuk tipe entitas tepercaya, pilih Alibaba Cloud Account.
-
Pilih Current Alibaba Cloud account dan klik OK.
-
Masukkan nama peran dan klik OK.
-
Di halaman manajemen peran RAM, klik Copy untuk menyimpan ARN peran tersebut.
Langkah 4: Buat kebijakan untuk unggahan file
Buat kebijakan kustom yang membatasi peran RAM hanya untuk mengunggah objek ke bucket tertentu.
-
Di panel navigasi kiri, pilih Permissions > Policies.
-
Klik Create Policy.
-
Di halaman Create Policy, klik tab JSON. Di dokumen kebijakan, ganti
<BucketName>denganweb-direct-upload, yaitu nama bucket yang Anda buat sebelumnya.{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "oss:PutObject", "Resource": "acs:oss:*:*:<BucketName>/*" } ] } -
Setelah mengonfigurasi kebijakan, klik OK.
-
Di kotak dialog Create Policy, masukkan Name untuk kebijakan tersebut dan klik OK.
Langkah 5: Berikan izin kepada peran RAM
Sambungkan kebijakan kustom ke peran RAM.
-
Di panel navigasi kiri, pilih Identities > Roles.
-
Di halaman Roles, temukan peran RAM target, lalu klik Add Permissions di kolom Actions.
-
Di halaman Add Permissions, pilih tab Custom Policy, lalu pilih kebijakan kustom yang Anda buat.
Atur Resource Scope menjadi Account Level.
-
Klik OK.
2. Dapatkan kredensial dan tanda tangan
Konfigurasikan accessKeyId, accessKeySecret, dan roleArn sebagai variabel lingkungan untuk menghindari hardcoding kredensial dalam kode Anda.
Tambahkan variabel lingkungan berikut.
Linux
-
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 -
Jalankan perintah berikut untuk menerapkan perubahan.
source ~/.bashrc -
Jalankan perintah berikut untuk memeriksa apakah variabel lingkungan telah diatur.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
macOS
-
Jalankan perintah berikut di terminal untuk memeriksa jenis shell default.
echo $SHELL -
Ikuti langkah-langkah sesuai jenis shell default Anda.
Zsh
-
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 -
Jalankan perintah berikut untuk menerapkan perubahan.
source ~/.zshrc -
Jalankan perintah berikut untuk memeriksa apakah variabel lingkungan telah diatur.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
Bash
-
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 -
Jalankan perintah berikut untuk menerapkan perubahan.
source ~/.bash_profile -
Jalankan perintah berikut untuk memeriksa apakah variabel lingkungan telah diatur.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
-
Windows
-
Jalankan perintah berikut di Command Prompt.
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" -
Buka jendela Command Prompt baru.
-
Di jendela Command Prompt baru, jalankan perintah berikut untuk memeriksa apakah 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 menggunakan Signature Version 4 (direkomendasikan). Topik policy form fields mencantumkan kondisi kebijakan yang tersedia.
Java
Di proyek Maven Anda, tambahkan dependensi berikut.
<!-- 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>
Gunakan kode contoh berikut untuk memperoleh kredensial akses sementara di server, menghitung tanda tangan POST, dan mengatur callback unggahan.
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.codehaus.jettison.json.JSONObject;
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 nama bucket, ID wilayah, dan host dengan nilai aktual Anda.
String bucket = "examplebucket";
String region = "cn-hangzhou";
String host = "http://examplebucket.oss-cn-hangzhou.aliyuncs.com";
// URL untuk callback unggahan. Ini harus berupa URL publik. Digunakan untuk komunikasi antara server aplikasi Anda dan OSS. Setelah file diunggah, OSS mengirim informasi unggahan ke server aplikasi Anda melalui URL ini.
String callbackUrl = "http://oss-demo.aliyuncs.com:23450/callback"; // URL server yang menerima permintaan callback. Contoh: http://oss-demo.aliyuncs.com:23450/callback.
// Awalan untuk file yang 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, contohnya "2014-12-01T12:00:00.000Z".
*/
public static String generateExpiration(long seconds) {
long now = Instant.now().getEpochSecond();
long expirationTime = now + seconds;
Instant instant = Instant.ofEpochSecond(expirationTime);
ZoneId zone = ZoneOffset.UTC;
ZonedDateTime zonedDateTime = instant.atZone(zone);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
String formattedDate = zonedDateTime.format(formatter);
return formattedDate;
}
// Menginisialisasi klien STS.
public static com.aliyun.sts20150401.Client createStsClient() throws Exception {
// Membocorkan kode proyek Anda dapat mengekspos pasangan AccessKey Anda, membahayakan keamanan semua sumber daya di bawah akun Anda. Kode contoh berikut hanya untuk referensi.
// Kami merekomendasikan menggunakan metode STS yang lebih aman.
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// Wajib. Pastikan variabel lingkungan OSS_ACCESS_KEY_ID diatur di lingkungan eksekusi Anda.
.setAccessKeyId(System.getenv("OSS_ACCESS_KEY_ID"))
// Wajib. Pastikan variabel lingkungan OSS_ACCESS_KEY_SECRET diatur di lingkungan eksekusi Anda.
.setAccessKeySecret(System.getenv("OSS_ACCESS_KEY_SECRET"));
// Untuk informasi lebih lanjut tentang endpoint, lihat https://api.aliyun.com/product/Sts
config.endpoint = "sts.cn-hangzhou.aliyuncs.com";
return new com.aliyun.sts20150401.Client(config);
}
// Memperoleh kredensial sementara dari STS.
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 eksekusi 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 {
// Saat menjalankan kode ini, cetak nilai kembali API untuk debugging.
AssumeRoleResponse response = client.assumeRoleWithOptions(assumeRoleRequest, runtime);
// Objek `credentials` berisi AccessKeyId, AccessKeySecret, dan SecurityToken.
return response.body.credentials;
} catch (TeaException error) {
// Ini hanya untuk tujuan demonstrasi. Tangani pengecualian dengan hati-hati dan jangan abaikan di proyek Anda.
System.out.println(error.getMessage());
System.out.println(error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error.message);
}
// Mengembalikan objek respons kesalahan 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 saat ini dalam format yyyyMMdd, digunakan untuk bidang x-oss-credential.
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: Bangun string yang akan ditandatangani.
String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes()));
// 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");
// Langkah 4: Hitung tanda tangan.
byte[] result = hmacsha256(signingKey, stringToSign);
String signature = BinaryUtil.toHex(result);
// Langkah 5: Konfigurasikan callback.
JSONObject jasonCallback = new JSONObject();
jasonCallback.put("callbackUrl", callbackUrl);
jasonCallback.put("callbackBody","filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
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);
response.put("callback", base64CallbackBody);
// 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 {
// Menginisialisasi spesifikasi kunci HMAC, mengatur algoritma ke HmacSHA256, dan menggunakan kunci yang disediakan.
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
// Mendapatkan instance Mac dan menggunakan metode getInstance untuk menentukan algoritma HmacSHA256.
Mac mac = Mac.getInstance("HmacSHA256");
// Menginisialisasi objek Mac dengan kunci.
mac.init(secretKeySpec);
// Menghitung hash HMAC dari 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
Gunakan kode contoh berikut untuk memperoleh kredensial akses sementara dari STS, membangun kebijakan unggahan, menghitung tanda tangan POST, dan mengatur callback.
from flask import Flask, render_template, jsonify, request
from alibabacloud_tea_openapi.models import Config
from alibabacloud_sts20150401.client import Client as Sts20150401Client
from alibabacloud_sts20150401 import models as sts_20150401_models
import os
import json
import base64
import hmac
import datetime
import time
import hashlib
import oss2
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 yang sebenarnya.
bucket = 'examplebucket'
region_id = 'cn-hangzhou'
host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'
# Waktu kedaluwarsa dalam detik.
expire_time = 3600
# Awalan untuk file yang diunggah ke OSS.
upload_dir = 'dir'
def hmacsha256(key, data):
"""
Fungsi untuk 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 dengan langsung meneruskan kredensial.
config = Config(
region_id=region_id,
access_key_id=access_key_id,
access_key_secret=access_key_secret
)
# Buat klien STS dan peroleh 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())
# Konversi stempel waktu ke objek datetime.
dt_obj = datetime.datetime.utcfromtimestamp(now)
# Atur waktu kedaluwarsa permintaan menjadi 3 jam dari waktu saat ini.
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')
# Definisikan fungsi untuk mengkodekan Base64 parameter callback.
def encode_callback(callback_params):
cb_str = json.dumps(callback_params).strip()
return oss2.compat.to_string(base64.b64encode(oss2.compat.to_bytes(cb_str)))
# Bangun konfigurasi callback dan kodekan Base64.
callback_config = {
"callbackUrl": "http://oss-demo.aliyuncs.com:23450/callback", # URL server callback Anda.
"callbackBody": "bucket=${bucket}&object=${object}&etag=${etag}&size=${size}",
"callbackBodyType": "application/x-www-form-urlencoded"
}
encoded_callback = encode_callback(callback_config)
# Bangun 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},
]
}
policy_str = json.dumps(policy).strip()
# Langkah 2: Bangun 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()
# Siapkan data tanggapan.
response_data = {
'policy': stringToSign, # Bidang formulir.
'x_oss_signature_version': "OSS4-HMAC-SHA256", # Versi dan algoritma tanda tangan. Nilainya tetap OSS4-HMAC-SHA256.
'x_oss_credential': f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request", # Set parameter yang menentukan kunci turunan.
'x_oss_date': dt_obj_1, # Waktu permintaan.
'signature': signature, # Informasi tanda tangan.
'host': host,
'dir': upload_dir,
'security_token': security_token, # Token keamanan.
'callback': encoded_callback # Konfigurasi callback yang dikodekan Base64.
}
return jsonify(response_data)
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000) # Jika Anda perlu mendengarkan alamat lain, seperti 0.0.0.0, Anda harus menambahkan mekanisme otentikasi pada server.
Node.js
Jalankan perintah berikut untuk menginstal dependensi.
npm install ali-oss
npm install @alicloud/credentials
npm install express
Gunakan kode contoh berikut untuk memperoleh kredensial akses sementara dari STS, membangun kebijakan unggahan, menghitung tanda tangan POST, dan mengatur callback.
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; // Port 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, // Peroleh ID AccessKey pengguna RAM dari variabel lingkungan.
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET // Peroleh rahasia AccessKey pengguna RAM dari variabel lingkungan.
});
// Panggil operasi assumeRole untuk memperoleh kredensial akses sementara dari STS.
const result = await sts.assumeRole(process.env.OSS_STS_ROLE_ARN, '', '3600', 'yourRoleSessionName'); // Peroleh ARN peran RAM dari variabel lingkungan, atur periode validitas kredensial akses sementara menjadi 3.600 detik, dan tentukan nama sesi peran kustom.
// 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 target Anda.
region: 'cn-hangzhou', // Ganti dengan wilayah bucket target Anda.
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 standar 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);
// URL untuk callback unggahan. Ini digunakan untuk komunikasi antara server aplikasi Anda dan OSS. Setelah file diunggah, OSS mengirim informasi unggahan ke server aplikasi Anda melalui URL ini. Misalnya, atur callbackUrl ke https://oss-demo.aliyuncs.com:23450.
// 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 berikut berisi bidang minimum yang diperlukan.
const policy = {
expiration: expirationDate.toISOString(),
conditions: [
{ 'bucket': 'examplebucket' }, // Ganti dengan nama bucket target Anda.
{ '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);
const callback = {
callbackUrl: 'http://oss-demo.aliyuncs.com:23450/callback',// URL server yang menerima permintaan callback. Contoh: http://oss-demo.aliyuncs.com:23450/callback.
callbackBody:// Konten callback, seperti ETag file dan tipe MIME sumber daya.
"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
callbackBodyType: "application/x-www-form-urlencoded",// Tipe konten callback.
};
// 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 untuk file yang diunggah ke OSS.
callback: Buffer.from(JSON.stringify(callback)).toString("base64"),// Encode objek JSON dalam Base64 menggunakan Buffer.from.
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 di server.
});
Go
Jalankan perintah berikut untuk menginstal dependensi.
go get -u github.com/aliyun/credentials-go
go mod tidy
Gunakan kode contoh berikut untuk memperoleh kredensial akses sementara dari STS, membangun kebijakan unggahan, menghitung tanda tangan POST, dan mengatur callback.
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 digunakan untuk 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"`
Callback string `json:"callback"`
}
type CallbackParam struct{
CallbackUrl string `json:"callbackUrl"`
CallbackBody string `json:"callbackBody"`
CallbackBodyType string `json:"callbackBodyType"`
}
func main() {
// Definisikan string alamat IP dan port default.
strIPPort := ":8080"
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("Example : go run test1.go 11.22.**.** 80 ")
fmt.Println("Example : go run test1.go 0.0.0.0 8080 ")
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 untuk path root.
http.HandleFunc("/", handlerRequest)
// Daftarkan fungsi untuk menangani permintaan untuk memperoleh 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 untuk 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 untuk memperoleh 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 tempat bucket berada.
region = "cn-hangzhou"
// Atur nama bucket.
bucketName = "examplebucket"
// Atur endpoint unggahan OSS.
host := fmt.Sprintf("https://%s.oss-%s.aliyuncs.com", bucketName, region)
// Atur direktori unggahan.
dir := "user-dir"
// callbackUrl adalah URL server yang menerima callback unggahan. Ganti alamat IP dan port dengan informasi aktual Anda.
callbackUrl := "http://oss-demo.aliyuncs.com:23450/callback";
config := new(credentials.Config).
SetType("ram_role_arn").
SetAccessKeyId(os.Getenv("OSS_ACCESS_KEY_ID")).
SetAccessKeySecret(os.Getenv("OSS_ACCESS_KEY_SECRET")).
SetRoleArn(os.Getenv("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)
}
// Peroleh kredensial dari penyedia kredensial.
cred, err := provider.GetCredential()
if err != nil {
log.Fatalf("GetCredential fail, err:%v", err)
}
// Bangun 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)
}
// Bangun string yang akan ditandatangani.
stringToSign := base64.StdEncoding.EncodeToString([]byte(policy))
hmacHash := func() hash.Hash { return sha256.New() }
// Bangun 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))
var callbackParam CallbackParam
callbackParam.CallbackUrl = callbackUrl
callbackParam.CallbackBody = "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}"
callbackParam.CallbackBodyType = "application/x-www-form-urlencoded"
callback_str,err:=json.Marshal(callbackParam)
if err != nil {
fmt.Println("callback json err:", err)
}
callbackBase64 := base64.StdEncoding.EncodeToString(callback_str)
// Bangun 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, // Endpoint unggahan OSS.
Dir: dir, // Direktori unggahan.
Callback: callbackBase64, // Parameter callback 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
Gunakan kode contoh berikut untuk memperoleh kredensial akses sementara dari STS, membangun kebijakan unggahan, menghitung tanda tangan POST, dan mengatur callback.
ke nama session kustom, misalnya oss-role-session.
// Ganti dengan ARN dari role 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')) // Ganti dengan ARN role RAM Anda.
->request();
// Dapatkan informasi kredensial dari hasil permintaan STS.
$tokenData = $result->get('Credentials');
// Bangun data JSON yang 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));
// Bangun kebijakan (policy).
$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);
// Buat string yang akan ditandatangani.
$stringToSign = base64_encode($policyStr);
// Hitung kunci penandatanganan (signing key).
$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);
$callback_param = array(
'callbackUrl' => $callbackUrl,
'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}',
'callbackBodyType' => "application/x-www-form-urlencoded"
);
$callback_string = json_encode($callback_param);
$base64_callback_body = base64_encode($callback_string);
// 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,
'callback' => $base64_callback_body,
];
header('Content-Type: application/json');
echo json_encode($responseData);
exit;
}
// Entri rute halaman utama.
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/') {
echo file_get_contents(__DIR__ . '/public/index.html');
exit;
}
// Entri rute lainnya.
http_response_code(404);
echo json_encode(['message' => 'Not Found']);
exit;
?> <?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 untuk file yang diunggah.
// $callbackUrl adalah URL server yang menerima callback unggahan. Ganti alamat IP dan port dengan URL aktual Anda.
$callbackUrl = 'http://oss-demo.aliyuncs.com:23450/callback';
// Hitung HMAC-SHA256.
function hmacsha256($key, $data) {
return hash_hmac('sha256', $data, $key, true);
}
// Tangani permintaan untuk memperoleh 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();
// Lakukan permintaan STS dan peroleh hasilnya.
// Atur <your_role_session_name> ke nama sesi kustom, misalnya, 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')) // Ganti dengan ARN peran RAM Anda.
->request();
// Peroleh informasi kredensial dari hasil permintaan STS.
$tokenData = $result->get('Credentials');
// Bangun data JSON yang 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));
// Bangun 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);
// Bangun 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);
$callback_param = array(
'callbackUrl' => $callbackUrl,
'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}',
'callbackBodyType' => "application/x-www-form-urlencoded"
);
$callback_string = json_encode($callback_param);
$base64_callback_body = base64_encode($callback_string);
// 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,
'callback' => $base64_callback_body,
];
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;
?></your_role_arn></your_role_session_name>
Parameter callback adalah string JSON yang di-encode Base64. Untuk membangunnya, tentukan callbackUrl (URL server yang menerima permintaan callback) dan callbackBody (konten callback).
{"callbackUrl":"http://oss-demo.aliyuncs.com:23450/callback",
"callbackBody":"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
"callbackBodyType":"application/x-www-form-urlencoded"}
|
Parameter |
Deskripsi |
|
callbackUrl |
URL server aplikasi yang menerima callback dari OSS. |
|
callbackBody |
Konten permintaan callback yang dikirim dari OSS ke server aplikasi. Ini dapat mencakup nama file, ukuran, dan tipe, atau tinggi dan lebar gambar. |
|
callbackBodyType |
Nilai yang valid:
|
Contoh ini menunjukkan konfigurasi callback dasar. Sesuaikan berdasarkan kebutuhan Anda. callback.
Langkah 3: Konfigurasikan klien web
Unggahan formulir klien web
Klien web membangun permintaan formulir HTML untuk mengunggah file langsung ke OSS.
Contoh respons
Server aplikasi mengembalikan respons berikut 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",
"callback":"eyJjYWxsYmFja1VybCI6Imh0dHA6Ly9vc3MtZGVtby5hbGl5dW5jcy5jb206MjM0NTAiLAoiY2FsbGJhY2tCb2R5IjoiZmlsZW5hbWU9JHtvYmplY3R9JnNpemU9JHtzaXplfSZtaW1lVHlwZT0ke21pbWVUeXBlfSZoZWlnaHQ9JHtpbWFnZUluZm8uaGVpZ2h0fSZ3aWR0aD0ke2ltYWdlSW5mby53aWR0aH0iLAoiY2FsbGJhY2tCb2R5VHlwZSI6ImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCJ9"
}
Bidang respons:
|
Parameter |
Deskripsi |
|
dir |
Membatasi unggahan ke awalan file tertentu. |
|
host |
Nama domain bucket. |
|
policy |
Kebijakan unggahan formulir. Post Policy. |
|
security_token |
Token keamanan. |
|
signature |
Tanda tangan yang dihitung dari kebijakan. Post Signature. |
|
x_oss_credential |
Menentukan parameter untuk kunci turunan. |
|
x_oss_date |
Timestamp permintaan dalam format ISO 8601. Contoh: |
|
x_oss_signature_version |
Versi dan algoritma tanda tangan. Nilainya selalu OSS4-HMAC-SHA256. |
|
callback |
Isi permintaan callback. |
-
Permintaan formulir mencakup konten file dan parameter yang diterima dari server aplikasi.
-
Klien web mengirim data ini sebagai permintaan POST multipart/form-data langsung ke OSS.
-
Kecuali bidang formulir
file, ukuran semua bidang formulir lainnya, termasukkey, tidak boleh melebihi 8 KB. -
Secara default, unggahan akan menimpa objek yang sudah ada dengan nama yang sama. Untuk mencegah hal ini, sertakan header
x-oss-forbid-overwritedalam permintaan unggahan dan atur nilainya ketrue. Jika objek dengan nama yang sama sudah ada, unggahan gagal, dan OSS mengembalikan errorFileAlreadyExists.
<!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 id="callback-info" class="mt-3" style="display: none;">
<h4>Informasi callback:</h4>
<pre id="callback-content"></pre>
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
const form = document.querySelector("form");
const fileInput = document.querySelector("#file");
const callbackInfo = document.querySelector("#callback-info");
const callbackContent = document.querySelector("#callback-content");
form.addEventListener("submit", (event) => {
event.preventDefault();
const file = fileInput.files[0];
if (!file) {
alert('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 memperoleh 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 file.
formData.append("x-oss-security-token", data.security_token);
formData.append("callback", data.callback); // Tambahkan parameter callback.
formData.append("file", file); // Bidang formulir 'file' harus yang terakhir.
return fetch(data.host, {
method: "POST",
body: formData
});
})
.then((response) => {
if (response.ok) {
console.log("Unggahan berhasil");
alert("File diunggah");
return response.json(); // Urai informasi callback.
} else {
console.log("Unggahan gagal dengan respons berikut:", response);
alert("Unggahan gagal. Silakan coba lagi nanti.");
}
})
.then((callbackData) => {
if (callbackData) {
callbackContent.textContent = JSON.stringify(callbackData, null, 2);
callbackInfo.style.display = "block";
}
})
.catch((error) => {
console.error("Terjadi kesalahan:", error);
});
});
});
</script>
</body>
</html>
-
Formulir HTML berisi bidang input file dan tombol submit, memungkinkan pengguna memilih file dan memulai unggahan.
-
Saat formulir dikirim, kode JavaScript mencegah perilaku pengiriman default. Kemudian mengirim permintaan AJAX ke server aplikasi untuk mengambil informasi tanda tangan yang diperlukan.
-
Setelah memperoleh informasi tanda tangan, bangun objek
FormDatayang berisi semua bidang formulir yang diperlukan. -
Kirim permintaan POST ke URL layanan OSS menggunakan metode
fetchuntuk mengunggah objek.
Jika unggahan berhasil, pesan "File diunggah" dan informasi callback apa pun akan ditampilkan. Jika unggahan gagal, pesan kesalahan akan ditunjukkan.
Verifikasi hasil
Uji fitur unggahan setelah penerapan.
-
Di browser Anda, buka alamat server, klik tombol Pilih File, pilih file, lalu unggah.
-
Di halaman Buckets, temukan bucket Anda dan verifikasi bahwa file telah berhasil diunggah.
Bersihkan resource
Hapus resource yang dibuat dalam tutorial ini untuk menghindari biaya berkelanjutan.
Lepaskan instance ECS
Melepas instance menghentikan penagihan dan menghapus datanya secara permanen.
-
Buka halaman Instances Konsol ECS. Temukan instance ECS target berdasarkan wilayah dan ID instansnya. Di kolom Actions, klik
. -
Pilih Release. Dari menu drop-down, pilih Release di bagian Instance Status.
-
Verifikasi bahwa Anda telah memilih instance yang benar, pilih Release Now, lalu klik Next.
-
Tinjau resource terkait yang akan dilepas dan akui risiko data. Kemudian, klik OK.
-
Disk sistem dan alamat IP publik yang ditetapkan dilepas bersama instance.
-
Grup keamanan, vSwitch, dan VPC tidak dilepas bersama instance. Resource ini gratis, sehingga Anda dapat memilih untuk menghapusnya sesuai kebutuhan bisnis Anda.
-
EIP tidak dilepas bersama instance dan bukan resource gratis. Anda dapat memilih untuk menghapusnya sesuai kebutuhan bisnis Anda.
Hapus bucket
-
Login ke Konsol OSS.
-
Di panel navigasi kiri, klik Buckets. Lalu, klik nama bucket target.
-
Hapus semua objek di bucket.
-
Di panel navigasi kiri, klik Delete Bucket.
Hapus pengguna RAM
-
Login ke Konsol RAM sebagai administrator RAM.
-
Di panel navigasi kiri, pilih Identities > Users.
-
Di halaman Users, temukan pengguna RAM yang akan dihapus dan klik Delete di kolom Actions.
Sebagai alternatif, untuk menghapus beberapa pengguna RAM sekaligus, pilih kotak centangnya dan klik Delete User di bagian bawah daftar. Tindakan ini memindahkan pengguna ke Keranjang daur ulang.
-
Di kotak dialog Delete User, tinjau dampak penghapusan, masukkan nama pengguna RAM untuk konfirmasi, lalu klik Move to Recycle Bin.
Hapus peran RAM
-
Login ke Konsol RAM sebagai administrator RAM.
-
Di panel navigasi kiri, pilih Identities > Roles.
-
Di halaman Roles, temukan peran RAM yang akan dihapus dan klik Delete Role di kolom Actions.
-
Di kotak dialog Delete Role, masukkan nama peran RAM untuk konfirmasi, lalu klik Delete Role.
CatatanJika kebijakan dilampirkan ke peran RAM, menghapus peran tersebut juga akan melepas kebijakan tersebut.
FAQ
Unggahan batch dari front end
OSS tidak menyediakan API unggahan batch. Unggah objek satu per satu dalam loop menggunakan prosedur yang sama.
Menyesuaikan header permintaan callback
Tidak. Anda dapat menyesuaikan parameter isi callback, tetapi tidak header permintaan.