Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa esercitazione illustra come caricare file da un browser direttamente in Archiviazione BLOB di Azure senza esporre le credenziali. Si utilizzerà TypeScript per implementare il modello Valet Key con token SAS (Shared Access Signature) e identità gestite per un'autenticazione sicura senza l'uso di chiavi.
L'applicazione di esempio include:
- API di Fastify che genera token SAS a tempo limitato
- Front-end React che carica i file direttamente in Archiviazione di Azure
- Infrastruttura come codice per la distribuzione con l'interfaccia della riga di comando per sviluppatori di Azure
Al termine di questa esercitazione si avrà un'applicazione funzionante distribuita in App Azure Container che illustra i caricamenti sicuri dei file senza esporre le credenziali di archiviazione al browser.
Prerequisiti
Prima di iniziare, assicurarsi di disporre di:
- Sottoscrizione di Azure: creare un account gratuitamente
- Un account GitHub per l'uso di GitHub Codespaces (include ore mensili gratuite)
Mancia
Questa esercitazione usa GitHub Codespaces, che fornisce un ambiente di sviluppo preconfigurato nel browser. Non è necessaria alcuna configurazione locale.
Architecture
Il front-end richiede un token SAS dall'API, quindi carica i file direttamente su Azure Storage. Dopo il caricamento, l'API elenca tutti i file caricati con token SAS di sola lettura per il loro display.
Concetti chiave
Token di firma di accesso condiviso per delega utente
L'applicazione utilizza i token SAS di delega utente per un'autenticazione sicura senza chiavi. Questi token vengono firmati con le credenziali di Microsoft Entra ID tramite l'identità gestita. L'API genera token di breve durata (10-60 minuti) con autorizzazioni specifiche (lettura, scrittura o eliminazione), consentendo al browser di caricare i file direttamente nella risorsa di archiviazione senza esporre le credenziali.
Distribuzione dell'interfaccia della riga di comando per sviluppatori di Azure
Distribuire l'infrastruttura completa con azd up. Questa procedura crea App contenitore di Azure per il frontend React e il backend API Fastify, configura le identità gestite e assegna le autorizzazioni di controllo degli accessi in base al ruolo (RBAC). L'infrastruttura usa modelli Bicep che seguono i principi di Azure Well-Architected Framework con i moduli verificati di Azure, se applicabile.
Ambiente di sviluppo in container
Il codice di esempio completo di questo tutorial utilizza un contenitore di sviluppo in GitHub Codespaces o in locale con Visual Studio Code.
Annotazioni
È anche possibile eseguire questa esercitazione in locale in Visual Studio Code con l'estensione Dev Containers. Il codice di esempio completo include la configurazione del contenitore di sviluppo.
Aprire l'esempio in GitHub Codespaces
GitHub Codespaces fornisce un ambiente VS Code basato su browser con tutte le dipendenze preinstallate.
Importante
Tutti gli account GitHub possono usare Codespaces con ore gratuite ogni mese. Per ulteriori informazioni, vedere GitHub Codespaces archiviazione e ore centrali inclusi mensilmente.
In un browser web, aprire il repository di esempio e selezionare Code>Crea uno spazio di codice su 'main'.
Attendere l'avvio del contenitore di sviluppo. Questo processo di avvio può richiedere alcuni minuti. I passaggi rimanenti di questa esercitazione si svolgono nel contesto di questo contenitore di sviluppo.
Distribuire l'esempio
Accedere ad Azure.
azd auth loginEffettuare il provisioning delle risorse e distribuire l'esempio nell'ambiente di hosting.
azd upQuando richiesto, immettere le informazioni seguenti:
Sollecito Entrare Immettere un nome di ambiente univoco secure-uploadSelezionare una sottoscrizione di Azure da usare Selezionare la sottoscrizione dall'elenco Immettere un valore per il parametro dell'infrastruttura "location" Selezionare le posizioni disponibili In alternativa, se si desidera visualizzare le risorse per cui è stato effettuato il provisioning ed esaminare l'output della distribuzione, è possibile eseguire il seguente comando per distribuire senza richieste:
azd provisionEseguire quindi questo comando per distribuire il codice dell'applicazione:
azd deploySe si modifica il codice dell'API o dell'app Web, è possibile ridistribuire solo il codice dell'applicazione con uno dei comandi seguenti:
azd deploy app azd deploy apiAl termine della distribuzione, prendere nota dell'URL dell'app Web distribuita visualizzata nel terminale.
(✓) Done: Deploying service app - Endpoint: https://app-gp2pofajnjhy6.calmtree-87e53015.eastus2.azurecontainerapps.io/Si tratta di un URL di esempio. L'URL sarà diverso.
Provare l’esempio
Aprire l'app Web distribuita in una nuova scheda del browser e selezionare un file PNG da caricare. Nella cartella
./docs/mediasono disponibili diversi file PNG.Selezionare Ottieni token SAS, quindi selezionare Carica file.
Visualizza il tuo file caricato nella galleria sotto il pulsante di caricamento.
Cos'è successo?
- Il file è stato caricato direttamente dal browser in Azure Storage usando un token SAS (Shared Access Signature) di sola scrittura limitato nel tempo.
- Le immagini della raccolta vengono caricate direttamente da Archiviazione Azure usando token di accesso condiviso (SAS) di sola lettura.
- Nessun segreto di autenticazione è stato esposto nel browser
Funzionamento del codice
Dopo aver visto l'applicazione in azione, esaminare il modo in cui il codice implementa caricamenti di file sicuri. L'applicazione ha due parti principali:
- Back-end API - esegue l'autenticazione con Azure e genera token SAS
- Front-end React - carica i file direttamente su Archiviazione di Azure usando token SAS
Le sezioni seguenti illustrano le implementazioni principali del codice.
Server API per generare token SAS ed elencare i file
Il server API esegue l'autenticazione in Archiviazione di Azure e genera token di firma di accesso condiviso con tempo limitato per l'uso del browser.
Autenticazione con identità gestita
L'applicazione usa chiavi di delega utente con identità gestita per l'autenticazione, ovvero l'approccio più sicuro per le applicazioni Azure.
ChainedTokenCredential prova i metodi di autenticazione in questo ordine:
-
In Azure:
ManagedIdentityCredential(identità delle app contenitore) -
Sviluppo locale:
AzureCliCredential(la tua sessioneaz 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;
}
Dopo l'autenticazione, creare un BlobServiceClient oggetto per interagire con Archiviazione di Azure:
// 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);
}
Generare token SAS con chiavi di delega utente
I token di firma di accesso condiviso richiedono una chiave di delega utente, che autentica il token usando le credenziali dell'ID di Microsoft Entra anziché le chiavi dell'account di archiviazione. La chiave è valida per un intervallo di tempo specifico:
const startsOn = new Date();
const expiresOn = new Date(startsOn.valueOf() + minutes * 60 * 1000);
const userDelegationKey = await blobServiceClient.getUserDelegationKey(
startsOn,
expiresOn
);
Generare token SAS di sola scrittura per i caricamenti di file
Per i caricamenti di file, l'API genera token di sola scrittura che non possono leggere o eliminare dati. I token scadono dopo 10 minuti:
// 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}`;
Livelli di autorizzazione disponibili:
-
'r'- Lettura (download/visualizzazione) -
'w'- Scrittura (caricamento/sovrascrittura) - Usato per i caricamenti -
'd'-Elimina -
'c'-Creare -
'a'- Aggiunta (BLOB di accodamento)
Generare token SAS di sola lettura per elencare e visualizzare i file
Per elencare e visualizzare i file, l'API genera token di sola lettura che scadono dopo 60 minuti:
// 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}`;
Il client dell'app Web richiede e riceve token SAS dal server API.
Il front-end React richiede token SAS dall'API e li usa per caricare direttamente i file in Azure Storage dal browser.
Il front-end segue un processo in tre passaggi:
- Richiedere un token SAS dall'API per un file specifico
- Carica direttamente in Archiviazione di Azure usando l'URL del token SAS (firma di accesso condiviso)
- Recuperare e visualizzare l'elenco dei file caricati con token SAS di sola lettura
Questa architettura mantiene il back-end leggero: genera solo token, non gestisce mai i dati dei file.
Richiedere un token SAS dell'Archiviazione Blob dal server API
Quando un utente seleziona un file e fa clic su "Get SAS Token", il frontend richiede un token di accesso condiviso di sola scrittura dall'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
});
};
Che succede:
- Invio frontend:
GET /api/sas?file=photo.jpg&permission=w&container=upload&timerange=10 - L'API restituisce:
{ url: "https://storageaccount.blob.core.windows.net/upload/photo.jpg?sv=2024-05-04&..." } - Questo URL è valido per 10 minuti e concede l'accesso in sola scrittura a tale BLOB specifico
Caricare direttamente su Blob Storage utilizzando il token SAS (firma di accesso condiviso)
Dopo aver ricevuto l'URL del token SAS, il front-end converte il file in ArrayBuffer e carica il file direttamente in Azure Storage, ignorando completamente l'API. Ciò riduce il carico del server e migliora le prestazioni.
Convertire il file in 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);
});
}
Usa quindi BlockBlobClient da @azure/storage-blob per caricare i dati del file usando l'URL del 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);
});
};
Punti principali:
- Il file non passa mai attraverso il server API
- Il caricamento passa direttamente dal browser ad Archiviazione di Azure
- Il token SAS autentica la richiesta.
- Nessun costo di elaborazione o larghezza di banda del server per la gestione dei file
Recuperare il file direttamente da Archiviazione di Azure e visualizzare l'immagine di anteprima
Dopo un caricamento riuscito, il front-end recupera un elenco di tutti i file nel contenitore. Ogni file nell'elenco include un proprio SAS token di sola lettura:
// 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
});
Esempio di risposta:
{
"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&..."
]
}
Il front-end utilizza gli URL SAS direttamente nei tag di immagine. Il browser recupera immagini da Archiviazione di Azure usando i token di sola lettura incorporati:
// 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>
Funzionamento:
- Ogni URL nell'elenco include un token SAS in modalità sola lettura (
sp=r) - Browser effettua richieste GET direttamente ad Azure Storage
- Nessuna autenticazione necessaria: il token si trova nell'URL
- I token scadono dopo 60 minuti (configurati nell'API)
Pulire le risorse
Al termine di questa esercitazione, rimuovere tutte le risorse di Azure per evitare addebiti in corso:
azd down
Risoluzione dei problemi
Segnalare problemi con questo esempio nel repository GitHub. Allegare i seguenti elementi al problema.
- URL dell'articolo
- Il passaggio o il contesto all'interno dell'articolo che è stato problematico
- Ambiente di sviluppo
Codice di esempio
- GitHub repository: Azure-Samples/azure-typescript-upload-file-storage-blob
Passaggi successivi
Dopo aver appreso come caricare in modo sicuro i file in Archiviazione di Azure, esplorare questi argomenti correlati:
- Documentazione di Archiviazione BLOB di Azure - Informazioni sui livelli di archiviazione, sulla gestione del ciclo di vita e sulle funzionalità avanzate
- pacchetto npm @azure/storage-blob - Esplorare le informazioni di riferimento complete sull'SDK e le funzionalità aggiuntive
- Modello Valet Key - Comprendere il modello architettonico alla base di questa soluzione
- Procedure consigliate per l'identità gestita - Proteggere le applicazioni di Azure