Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Tutorial ini menunjukkan kepada Anda cara mengunggah file dari browser langsung ke Azure Blob Storage tanpa mengekspos kredensial. Anda akan menggunakan TypeScript untuk menerapkan pola Kunci Valet dengan token Tanda Tangan Akses Bersama (SAS) dan Identitas Terkelola untuk autentikasi tanpa kunci yang aman.
Aplikasi sampel meliputi:
- Fastify API yang menghasilkan token SAS berbatas waktu
- Frontend React yang mengunggah file langsung ke Azure Storage
- Infrastruktur sebagai kode untuk penerapan dengan Azure Developer CLI
Pada akhir tutorial ini, Anda akan memiliki aplikasi kerja yang disebarkan ke Azure Container Apps yang menunjukkan unggahan file aman tanpa mengekspos kredensial penyimpanan ke browser.
Prasyarat
Sebelum memulai, pastikan Anda memiliki:
- Langganan Azure - buat satu secara gratis
- Akun GitHub untuk menggunakan GitHub Codespaces (termasuk jam bulanan gratis)
Tips
Tutorial ini menggunakan GitHub Codespaces, yang menyediakan lingkungan pengembangan yang telah dikonfigurasi sebelumnya di browser Anda. Tidak diperlukan penyiapan lokal.
Architecture
Frontend meminta token SAS dari API, lalu mengunggah file langsung ke Azure Storage. Setelah diunggah, API mencantumkan semua file yang diunggah dengan token SAS yang hanya bisa dibaca untuk ditampilkan.
Konsep utama
Token SAS untuk Delegasi Pengguna
Aplikasi ini menggunakan token SAS Delegasi Pengguna untuk autentikasi tanpa kunci yang aman. Token ini ditandatangani dengan kredensial ID Microsoft Entra melalui Identitas Terkelola. API menghasilkan token berumur pendek (10-60 menit) dengan izin tertentu (baca, tulis, atau hapus), memungkinkan browser mengunggah file langsung ke penyimpanan tanpa mengekspos info masuk.
Penyebaran Azure Developer CLI
Sebarkan infrastruktur lengkap dengan azd up. Ini menyediakan Azure Container Apps untuk backend React dan Fastify API, mengonfigurasi identitas terkelola, dan menetapkan izin RBAC. Infrastruktur ini menggunakan templat Bicep yang mengikuti prinsip-prinsip Azure Well-Architected Framework dengan Modul Azure yang Terverifikasi jika berlaku.
Lingkungan pengembangan kontainer
Kode sampel lengkap tutorial ini menggunakan kontainer pengembangan di GitHub Codespaces atau Visual Studio Code lokal.
Nota
Anda juga dapat menjalankan tutorial ini secara lokal di Visual Studio Code dengan ekstensi Kontainer Dev. Kode sampel lengkap mencakup konfigurasi kontainer pengembangan.
Buka sampel di GitHub Codespaces
GitHub Codespaces menyediakan lingkungan VS Code berbasis browser dengan semua dependensi sudah terinstal.
Penting
Semua akun GitHub dapat menggunakan Codespace dengan jam gratis setiap bulan. Untuk informasi selengkapnya, lihat GitHub Codespaces bulanan yang disertakan penyimpanan dan jam inti.
Di browser web, buka repositori sampel dan pilih Kode>Buat ruang kode di utama.
Tunggu hingga kontainer pengembangan dimulai. Proses startup ini dapat memakan waktu beberapa menit. Langkah-langkah yang tersisa dalam tutorial ini berlangsung dalam konteks kontainer pengembangan ini.
Menyebarkan sampel
Masuk ke Azure.
azd auth loginProvisikan sumber daya dan sebarkan sampel ke lingkungan hosting.
azd upSaat diminta, masukkan informasi berikut:
Cepat Masuk Masukkan nama lingkungan yang unik secure-uploadPilih Langganan Azure yang akan digunakan Pilih langganan Anda dari daftar Masukkan nilai untuk parameter infrastruktur 'lokasi' Pilih dari lokasi yang tersedia Atau, jika Anda ingin melihat sumber daya yang disediakan lalu melihat output penyebaran, Anda dapat menjalankan perintah berikut untuk menyebarkan tanpa perintah:
azd provisionKemudian jalankan perintah ini untuk menyebarkan kode aplikasi:
azd deployJika Anda mengubah API atau kode aplikasi web, Anda dapat menyebarkan ulang kode aplikasi hanya dengan salah satu perintah berikut:
azd deploy app azd deploy apiSetelah penyebaran selesai, perhatikan URL aplikasi web yang disebarkan yang ditampilkan di terminal.
(✓) Done: Deploying service app - Endpoint: https://app-gp2pofajnjhy6.calmtree-87e53015.eastus2.azurecontainerapps.io/Ini adalah contoh URL. URL Anda akan berbeda.
Coba sampel
Buka aplikasi web yang disebarkan di tab browser baru dan pilih file PNG untuk diunggah. Beberapa file PNG tersedia di
./docs/mediafolder .Pilih Dapatkan token SAS, lalu pilih Unggah file.
Lihat file yang Anda unggah di galeri di bawah tombol unggah.
Apa yang baru saja terjadi?
- File Anda diunggah langsung dari browser ke Azure Storage menggunakan token SAS terbatas waktu dan hanya tulis
- Gambar galeri dimuat langsung dari Azure Storage dengan menggunakan token SAS baca saja.
- Tidak ada rahasia autentikasi yang terekspos di browser Anda
Cara kerja kode
Sekarang setelah Anda melihat aplikasi beraksi, jelajahi cara kode menerapkan unggahan file yang aman. Aplikasi ini memiliki dua bagian utama:
- Backend API - Mengautentikasi dengan Azure dan menghasilkan token SAS
- Frontend React - Mengunggah file langsung ke Azure Storage menggunakan token SAS
Bagian berikut menelusuri implementasi kode kunci.
Server API untuk menghasilkan token SAS dan mencantumkan file
Server API mengautentikasi ke Azure Storage dan menghasilkan token SAS terbatas waktu untuk digunakan browser.
Autentikasi dengan Identitas Terkelola
Aplikasi ini menggunakan Kunci Delegasi Pengguna dengan Identitas Terkelola untuk autentikasi, yang merupakan pendekatan paling aman untuk aplikasi Azure.
ChainedTokenCredential mencoba metode autentikasi dalam urutan ini:
-
Di Azure:
ManagedIdentityCredential(Identitas Aplikasi Kontainer) -
Pengembangan lokal:
AzureCliCredential(sesi Andaaz login)
// From: packages/api/src/lib/azure-storage.ts
export function getCredential(): ChainedTokenCredential {
if (!_credential) {
const clientId = process.env.AZURE_CLIENT_ID;
// Create credential chain with ManagedIdentity first
const credentials = [
new ManagedIdentityCredential(clientId ? { clientId } : undefined),
new AzureCliCredential()
];
_credential = new ChainedTokenCredential(...credentials);
}
return _credential;
}
Setelah autentikasi, buat BlobServiceClient untuk berinteraksi dengan Azure Storage:
// From: packages/api/src/lib/azure-storage.ts
export function getBlobServiceClient(accountName: string): BlobServiceClient {
const credential = getCredential();
const url = `https://${accountName}.blob.core.windows.net`;
return new BlobServiceClient(url, credential);
}
Membuat token SAS dengan Kunci Delegasi Pengguna
Token SAS memerlukan Kunci Delegasi Pengguna, yang mengautentikasi token menggunakan kredensial ID Microsoft Entra alih-alih kunci akun penyimpanan. Kunci ini valid untuk rentang waktu tertentu:
const startsOn = new Date();
const expiresOn = new Date(startsOn.valueOf() + minutes * 60 * 1000);
const userDelegationKey = await blobServiceClient.getUserDelegationKey(
startsOn,
expiresOn
);
Menghasilkan token SAS tulis-saja untuk unggahan file
Untuk unggahan file, API menghasilkan token tulis-saja yang tidak dapat membaca atau menghapus data. Token kedaluwarsa setelah 10 menit:
// From: packages/api/src/routes/sas.ts
const DEFAULT_SAS_TOKEN_PERMISSION = 'w';
const DEFAULT_SAS_TOKEN_EXPIRATION_MINUTES = 10;
const sasToken = generateBlobSASQueryParameters(
{
containerName: container,
blobName: file,
permissions: BlobSASPermissions.parse(permission),
startsOn,
expiresOn
},
userDelegationKey,
accountName
).toString();
const sasUrl = `${blobClient.url}?${sasToken}`;
Tingkat izin yang tersedia:
-
'r'- Baca (unduh/lihat) -
'w'- Tulis (unggah/timpa) - Digunakan untuk unggahan -
'd'-Menghapus -
'c'-Membuat -
'a'- Tambahkan (lampirkan blob)
Membuat token SAS baca-saja untuk mencantumkan dan menampilkan file
Untuk mencantumkan dan menampilkan file, API menghasilkan token baca-saja yang kedaluwarsa setelah 60 menit:
// From: packages/api/src/routes/list.ts
const LIST_SAS_TOKEN_PERMISSION = 'r';
const LIST_SAS_TOKEN_EXPIRATION_MINUTES = 60;
const sasToken = generateBlobSASQueryParameters(
{
containerName: container,
blobName: blob.name,
permissions: BlobSASPermissions.parse(LIST_SAS_TOKEN_PERMISSION),
startsOn,
expiresOn
},
userDelegationKey,
accountName
).toString();
const sasUrl = `${blobClient.url}?${sasToken}`;
Permintaan klien aplikasi web dan menerima token SAS dari server API
Frontend React meminta token SAS dari API dan menggunakannya untuk langsung mengunggah file ke Azure Storage dari browser.
Frontend mengikuti proses tiga langkah:
- Meminta token SAS dari API untuk file tertentu
- Mengunggah langsung ke Azure Storage menggunakan URL token SAS
- Mengambil dan menampilkan daftar file yang diunggah dengan token SAS baca-saja
Arsitektur ini menjaga backend tetap ringan - hanya menghasilkan token, tidak pernah menangani data file.
Meminta Token SAS Blob Storage dari server API
Saat pengguna memilih file dan mengklik "Dapatkan Token SAS", frontend meminta token SAS tulis-saja dari API:
// From: packages/app/src/App.tsx
const handleFileSasToken = () => {
const permission = 'w'; // write-only
const timerange = 10; // 10 minutes expiration
if (!selectedFile) return;
// Build API request URL
const url = `${API_URL}/api/sas?file=${encodeURIComponent(
selectedFile.name
)}&permission=${permission}&container=${containerName}&timerange=${timerange}`;
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then((response) => {
if (!response.ok) {
throw new Error(`Error: ${response.status} ${response.statusText}`);
}
return response.json();
})
.then((data: SasResponse) => {
const { url } = data;
setSasTokenUrl(url); // Store the SAS URL for upload
});
};
Apa yang terjadi:
- Frontend mengirimkan:
GET /api/sas?file=photo.jpg&permission=w&container=upload&timerange=10 - API mengembalikan:
{ url: "https://storageaccount.blob.core.windows.net/upload/photo.jpg?sv=2024-05-04&..." } - URL ini berlaku selama 10 menit dan memberikan akses tulis-saja ke blob tertentu
Mengunggah langsung ke Blob Storage menggunakan token SAS
Setelah URL token SAS diterima, frontend mengonversi file ke ArrayBuffer dan mengunggah file langsung ke Azure Storage - melewati API sepenuhnya. Ini mengurangi beban server dan meningkatkan performa.
Mengonversi file ke ArrayBuffer.
// From: packages/app/src/lib/convert-file-to-arraybuffer.ts
export function convertFileToArrayBuffer(file: File): Promise<ArrayBuffer | null> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const arrayBuffer = reader.result;
resolve(arrayBuffer as ArrayBuffer);
};
reader.onerror = () => {
reject(new Error('Error reading file.'));
};
reader.readAsArrayBuffer(file);
});
}
Kemudian, gunakan BlockBlobClient dari @azure/storage-blob untuk mengunggah data file menggunakan URL token SAS.
// From: packages/app/src/App.tsx
const handleFileUpload = () => {
console.log('SAS Token URL:', sasTokenUrl);
// Convert file to ArrayBuffer
convertFileToArrayBuffer(selectedFile as File)
.then((fileArrayBuffer) => {
if (fileArrayBuffer === null || fileArrayBuffer.byteLength < 1) {
throw new Error('Failed to convert file to ArrayBuffer');
}
// Create Azure Storage client with SAS URL
const blockBlobClient = new BlockBlobClient(sasTokenUrl);
// Upload directly to Azure Storage
return blockBlobClient.uploadData(fileArrayBuffer);
})
.then((uploadResponse) => {
if (!uploadResponse) {
throw new Error('Upload failed - no response from Azure Storage');
}
setUploadStatus('Successfully finished upload');
// After upload, fetch the updated list of files
const listUrl = `${API_URL}/api/list?container=${containerName}`;
return fetch(listUrl);
});
};
Poin-poin penting:
- File tidak pernah melewati server API Anda
- Unggahan langsung dari browser ke Azure Storage
- Token SAS mengautentikasi permintaan
- Tidak ada bandwidth server atau biaya pemrosesan untuk penanganan file
Ambil file langsung dari Azure Storage dan tampilkan gambar mini
Setelah unggahan berhasil, frontend mengambil daftar semua file dalam kontainer. Setiap file dalam daftar dilengkapi dengan token SAS baca-saja sendiri:
// From: packages/app/src/App.tsx
const listUrl = `${API_URL}/api/list?container=${containerName}`;
fetch(listUrl)
.then((response) => {
if (!response.ok) {
throw new Error(`Error: ${response.status}`);
}
return response.json();
})
.then((data: ListResponse) => {
setList(data.list); // Array of SAS URLs with read permission
});
Contoh respons:
{
"list": [
"https://storageaccount.blob.core.windows.net/upload/photo1.jpg?sv=2024-05-04&se=2025-12-18T15:30:00Z&sr=b&sp=r&...",
"https://storageaccount.blob.core.windows.net/upload/photo2.jpg?sv=2024-05-04&se=2025-12-18T15:30:00Z&sr=b&sp=r&..."
]
}
Frontend menggunakan URL SAS langsung dalam tag gambar. Browser mengambil gambar dari Azure Storage menggunakan token baca-saja yang disematkan:
// From: packages/app/src/App.tsx
<Grid container spacing={2}>
{list.map((item) => {
const urlWithoutQuery = item.split('?')[0];
const filename = urlWithoutQuery.split('/').pop() || '';
const isImage = filename.endsWith('.jpg') ||
filename.endsWith('.png') ||
filename.endsWith('.jpeg');
return (
<Grid item xs={6} sm={4} md={3} key={item}>
<Card>
{isImage ? (
<CardMedia component="img" image={item} alt={filename} />
) : (
<Typography>{filename}</Typography>
)}
</Card>
</Grid>
);
})}
</Grid>
Cara kerjanya:
- Setiap URL dalam daftar menyertakan token SAS hanya-baca (
sp=r) - Browser membuat permintaan GET langsung ke Azure Storage
- Tidak diperlukan autentikasi - token ada di URL
- Token kedaluwarsa setelah 60 menit (dikonfigurasi dalam API)
Membersihkan sumber daya
Setelah selesai dengan tutorial ini, hapus semua sumber daya Azure untuk menghindari biaya berkelanjutan.
azd down
Pemecahan masalah
Laporkan masalah dengan sampel ini di repositori GitHub. Sertakan hal-hal berikut dengan masalah:
- URL dari artikel
- Langkah atau konteks dalam artikel yang bermasalah
- Lingkungan pengembangan Anda
Contoh kode
- Repositori GitHub: Azure-Samples/azure-typescript-upload-file-storage-blob
Langkah selanjutnya
Sekarang setelah Anda mempelajari cara mengunggah file dengan aman ke Azure Storage, jelajahi topik terkait ini:
- Dokumentasi Azure Blob Storage - Pelajari tentang tingkat penyimpanan, manajemen siklus hidup, dan fitur tingkat lanjut
- paket npm @azure/storage-blob - Jelajahi referensi SDK lengkap dan kemampuan tambahan
- Pola Kunci Valet - Pahami pola arsitektur di balik solusi ini
- Praktik terbaik Identitas Terkelola - Mengamankan aplikasi Azure Anda