Oktatóanyag: Kép feltöltése Egy Azure Storage-blobba TypeScript használatával

Ez az oktatóanyag bemutatja, hogyan tölthet fel fájlokat közvetlenül egy böngészőből az Azure Blob Storage-ba hitelesítő adatok felfedése nélkül. A TypeScript használatával implementálhatja a Valet kulcsmintát közös hozzáférésű jogosultságkód (SAS) jogkivonatokkal és felügyelt identitással a biztonságos, kulcs nélküli hitelesítéshez.

A mintaalkalmazás a következőket tartalmazza:

  • Fastify API, amely időkorlátos SAS-jogkivonatokat hoz létre
  • Egy React-előtér, amely közvetlenül az Azure Storage-ba tölti fel a fájlokat
  • Infrastruktúra az üzembe helyezés kódjaként az Azure Developer CLI-vel

Az oktatóanyag végére üzembe fog helyezni egy működő alkalmazást az Azure Container Appsben, amely bemutatja a biztonságos fájlfeltöltéseket anélkül, hogy tárterület-hitelesítő adatokat ad meg a böngészőnek.

Előfeltételek

Mielőtt hozzákezdene, győződjön meg arról, hogy:

  • Azure-előfizetés – [hozzon létre egyet ingyenesen][ingyenes Azure fiók]
  • GitHub-fiók a GitHub Codespaces használatához (beleértve az ingyenes havi órákat)

Borravaló

Ez az oktatóanyag a GitHub Codespacest használja, amely előre konfigurált fejlesztési környezetet biztosít a böngészőben. Nincs szükség helyi beállításra.

Architecture

A feltöltési folyamatot ábrázoló Azure-architektúradiagram: A felhasználó kiválasztja a fájlt a Web App Frontendben, a frontend SAS-jogkivonatot kér az API App háttérrendszeréből, a háttérrendszer lekéri a felhasználódelegálási kulcsot a felügyelt identitásból, és SAS-jogkivonatot hoz létre a Storage Blob-tárolóból, a frontend közvetlenül a fájlokat a Storage-ba tölti fel SAS-jogkivonat használatával, a háttérrendszer lekérdezi a Storage-t a feltöltött fájlok listázásához. A Container Registry konténerképeket biztosít mindkét alkalmazáshoz.

Az előtér SAS-jogkivonatot kér az API-tól, majd feltölti a fájlokat közvetlenül az Azure Storage-ba. A feltöltés után az API felsorolja az összes feltöltött fájlt, és csak olvasható SAS-jogkivonatokkal jeleníti meg.

Képernyőkép egy

Főbb fogalmak

Felhasználói delegálási SAS-jogkivonatok

Az alkalmazás felhasználói delegálási SAS-jogkivonatokat használ a biztonságos, kulcs nélküli hitelesítéshez. Ezek a tokenek a Microsoft Entra ID azonosító hitelesítő adataival vannak aláírva felügyelt identitáson keresztül. Az API rövid élettartamú jogkivonatokat (10–60 perc) hoz létre meghatározott engedélyekkel (olvasás, írás vagy törlés), így a böngésző közvetlenül a hitelesítő adatok felfedése nélkül tölthet fel fájlokat a tárolóba.

Azure Developer CLI üzembe helyezése

A teljes infrastruktúrát üzembe helyezheti a azd up segítségével. Ez kiépíti az Azure Container Appst a React előtér- és Fastify API-háttérrendszerhez, konfigurálja a felügyelt identitásokat, és RBAC-engedélyeket rendel hozzá. Az infrastruktúra Az Azure Well-Architected-keretrendszer alapelveit követve Bicep-sablonokat használ, ahol alkalmazható az Azure Verified Modules.

Fejlesztői tárolókörnyezet

Az oktatóanyag teljes mintakódja egy fejlesztői tárolót használ a GitHub Codespacesben vagy a helyi Visual Studio Code-ban.

Megjegyzés:

Ezt az oktatóanyagot helyileg is futtathatja a Visual Studio Code-ban a Dev Containers bővítménnyel. A teljes mintakód tartalmazza a fejlesztési tároló konfigurációját.

A minta megnyitása a GitHub Codespacesben

A GitHub Codespaces egy böngészőalapú VS Code-környezetet biztosít, amely minden függőséget előre telepített.

Fontos

Minden GitHub-fiók havonta ingyenes órákkal használhatja a Codespace-eket. További információért lásd: GitHub Codespaces havi tárhely- és alapórák tartalmazása .

  1. Egy webböngészőben nyissa meg a mintaadattárat, és válassza a Code> létrehozása) lehetőséget a főkiszolgálón.

    Képernyőkép a GitHub-adattár oldaláról, amelyen ki van emelve a Fájl megnyitása, a Fájl hozzáadása és a Zöld kód gomb.

  2. Várja meg, amíg a fejlesztési tároló elindul. Ez az indítási folyamat eltarthat néhány percig. Az oktatóanyag további lépései ennek a fejlesztési tárolónak a kontextusában történnek.

A minta üzembe helyezése

  1. Jelentkezzen be az Azure-ba.

    azd auth login
    
  2. Erőforrások kiépítése és a minta üzembe helyezése az üzemeltetési környezetben.

    azd up
    

    Amikor a rendszer kéri, adja meg a következő adatokat:

    Haladéktalan Belép
    Adjon meg egy egyedi környezetnevet secure-upload
    Válasszon ki egy Azure-előfizetést a használathoz Válassza ki előfizetését a listából
    Adjon meg egy értéket a "location" infrastruktúraparaméterhez Válasszon az elérhető helyek közül

    Másik lehetőségként, ha látni szeretné a kiépített erőforrásokat, majd látni szeretné az üzembe helyezés kimenetét, a következő parancsot futtathatja az üzembe helyezéshez kérések nélkül:

    azd provision
    

    Ezután futtassa ezt a parancsot az alkalmazáskód üzembe helyezéséhez:

    azd deploy
    

    Ha módosítja az API- vagy webalkalmazás-kódot, az alábbi parancsok egyikével újra üzembe helyezheti csak az alkalmazáskódot:

    azd deploy app
    azd deploy api
    
  3. Ha az üzembe helyezés befejeződött, jegyezze fel a terminálban megjelenített üzembe helyezett webalkalmazás URL-címét.

      (✓) Done: Deploying service app
      - Endpoint: https://app-gp2pofajnjhy6.calmtree-87e53015.eastus2.azurecontainerapps.io/
    

    Ez egy példa URL-cím. Az URL-címe eltérő lesz.

Próbálja ki a mintát

  1. Nyissa meg az üzembe helyezett webalkalmazást egy új böngészőlapon, és válasszon egy feltöltendő PNG-fájlt. A mappában ./docs/media több PNG-fájl is elérhető.

    Képernyőkép a fájlok Azure Storage-ba való feltöltésére szolgáló webalkalmazásról, amelyen a Fájl kiválasztása gomb és a tárolónév feltöltése látható.

  2. Válassza az SAS-jogkivonat lekérése, majd a Fájl feltöltése lehetőséget.

  3. A feltöltött fájl megtekintése a feltöltés gomb alatti katalógusban.

    Képernyőkép a webalkalmazásról, miután feltöltötte daisies.jpg az Azure Storage-ba, és megjeleníti a fájl nevét, az SAS URL-címét, a feltöltés állapotát és a kép miniatűrjeit.

Mi történt?

  • A fájlt közvetlenül a böngészőből töltötte fel az Azure Storage-ba egy időkorlátos, csak írásra érvényes SAS-jogkivonat használatával.
  • A galériaképek közvetlenül az Azure Storage-ból töltődnek fel csak olvasható SAS-jogkivonatokkal.
  • Nem tették közzé a hitelesítési titkos kulcsokat a böngészőben

A kód működése

Most, hogy már működés közben látta az alkalmazást, ismerje meg, hogyan valósítja meg a kód a biztonságos fájlfeltöltéseket. Az alkalmazás két fő részből áll:

  1. API-háttérrendszer – Hitelesítés az Azure-ral és SAS-jogkivonatok létrehozása
  2. React frontend – Fájlok feltöltése közvetlenül az Azure Storage-ba SAS-jogkivonatok használatával

A következő szakaszok végigvezetik a kulcskód implementációit.

API-kiszolgáló SAS-jogkivonatok és listafájlok létrehozásához

Az API-kiszolgáló hitelesíti az Azure Storage-t, és időkorlátos SAS-jogkivonatokat hoz létre a böngésző számára.

Hitelesítés felügyelt identitással

Az alkalmazás a felügyelt identitással rendelkező felhasználói delegálási kulcsokat használja a hitelesítéshez, ami az Azure-alkalmazások legbiztonságosabb megközelítése. A ChainedTokenCredential hitelesítési módszerek a következő sorrendben próbálkoznak:

  1. Az Azure-ban: ManagedIdentityCredential (Container Apps-identitás)
  2. Helyi fejlesztés: AzureCliCredential (a az login munkamenet)
// 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;
}

A hitelesítés után hozzon létre egy BlobServiceClient , az Azure Storage-ral való interakcióhoz:

// 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);
}

SAS-jogkivonatok létrehozása felhasználói delegálási kulcsokkal

Az SAS-jogkivonatokhoz felhasználói delegálási kulcs szükséges, amely a tárfiókkulcsok helyett a Microsoft Entra ID hitelesítő adataival hitelesíti a jogkivonatot. A kulcs egy adott időtartományra érvényes:

const startsOn = new Date();
const expiresOn = new Date(startsOn.valueOf() + minutes * 60 * 1000);

const userDelegationKey = await blobServiceClient.getUserDelegationKey(
  startsOn,
  expiresOn
);

Csak írásra szolgáló SAS-jogkivonatok létrehozása fájlfeltöltésekhez

Fájlfeltöltések esetén az API írásvédett jogkivonatokat hoz létre, amelyek nem tudnak adatokat olvasni vagy törölni. A tokenek 10 perc után lejárnak.

// 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}`;

Elérhető jogosultsági szintek:

  • 'r' - Olvasás (letöltés/megtekintés)
  • 'w' - Írás (feltöltés/felülírás) – Feltöltésekhez használatos
  • 'd' -Töröl
  • 'c' -Létrehozása
  • 'a' - Hozzáadás (Hozzáfűző Blokkok)

Olyan írásvédett SAS-jogkivonatok létrehozása, amelyek használhatók fájlok listázásához és megtekintéséhez

Fájlok listázásához és megjelenítéséhez az API csak olvasható jogkivonatokat hoz létre, amelyek 60 perc elteltével lejárnak.

// 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}`;

Webalkalmazás-ügyfél kérése és SAS-jogkivonatok fogadása az API-kiszolgálóról

A React előtér SAS-jogkivonatokat kér az API-tól, és a böngészőből közvetlenül feltölt fájlokat az Azure Storage-ba.

Az előtér egy háromlépéses folyamatot követ:

  1. SAS-jogkivonat kérése az API-tól egy adott fájlhoz
  2. Feltöltés közvetlenül az Azure Storage-ba az SAS-jogkivonat URL-címével
  3. A feltöltött fájlok listájának lekérése és megjelenítése írásvédett SAS-tokenekkel

Ez az architektúra könnyűvé teszi a háttérrendszert – csak jogkivonatokat hoz létre, soha nem kezeli a fájladatokat.

Blob Storage SAS-jogkivonat kérése az API-kiszolgálótól

Amikor egy felhasználó kiválaszt egy fájlt, és a "SAS-jogkivonat lekérése" lehetőséget választja, az előtér egy írásvédett SAS-jogkivonatot kér az API-tól:

// 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
    });
};

Mi történik:

  • Előtérbeli küldés: GET /api/sas?file=photo.jpg&permission=w&container=upload&timerange=10
  • Az API a következőket adja vissza: { url: "https://storageaccount.blob.core.windows.net/upload/photo.jpg?sv=2024-05-04&..." }
  • Ez az URL-cím 10 percig érvényes, és írásvédett hozzáférést biztosít az adott blobhoz

Feltöltés közvetlenül a Blob Storage-ba az SAS-jogkivonat használatával

Az SAS-jogkivonat URL-címének beérkezése után az előtér tömbbufferzé alakítja a fájlt, és feltölti a fájlt közvetlenül az Azure Storage-ba – az API teljes megkerülésével. Ez csökkenti a kiszolgáló terhelését, és javítja a teljesítményt.

Konvertálja a fájlt Tömbbufferre.

// 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);
  });
}

Ezután a BlockBlobClient forrás @azure/storage-blob használatával töltse fel a fájladatokat az SAS-jogkivonat URL-címével.

// 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);
    });
};

Főbb pontok:

  • A fájl soha nem halad át az API-kiszolgálón
  • A feltöltés közvetlenül a böngészőből az Azure Storage-ba kerül
  • Az SAS-jogkivonat hitelesíti a kérést
  • Nincs kiszolgálói sávszélesség vagy a fájlkezelés feldolgozási költsége

A fájl lekérése közvetlenül az Azure Storage-ból, és a miniatűr képének megjelenítése

A sikeres feltöltés után az előtér lekéri a tárolóban lévő összes fájl listáját. A listában szereplő összes fájl saját írásvédett SAS-jogkivonattal rendelkezik:

// 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
  });

Példa válaszra:

{
  "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&..."
  ]
}

A frontend közvetlenül használja az SAS URL-címeket az img címkékben. A böngésző a beágyazott írásvédett jogkivonatokkal az Azure Storage-ból lekéri a képeket.

// 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>

Hogyan működik:

  • A lista minden URL-címe tartalmaz egy írásvédett SAS-jogkivonatot (sp=r)
  • A böngésző get kéréseket küld közvetlenül az Azure Storage-ba
  • Nincs szükség hitelesítésre – a jogkivonat az URL-címben található
  • A jogkivonatok 60 perc után lejárnak (az API-ban konfigurálva)

Erőforrások törlése

Ha befejezte ezt az oktatóanyagot, távolítsa el az összes Azure-erőforrást a folyamatos költségek elkerülése érdekében:

azd down

Hibaelhárítás

Jelentse a gitHub-adattárban a mintával kapcsolatos problémákat . Adja meg a következőt a problémával kapcsolatban:

  • A cikk URL-címe
  • A cikk azon lépése vagy környezete, amely problémás volt
  • Az Ön fejlesztési környezete

Mintakód