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.
In questa guida rapida, si crea un'applicazione web che visualizza immagini satellitari e dati geospaziali dal tuo GeoCatalog su una mappa interattiva. È possibile autenticare gli utenti con Microsoft Entra ID, eseguire query su raccolte STAC ed eseguire il rendering dei riquadri della mappa, tutti dal browser JavaScript.
Cosa si apprende:
- Autenticare gli utenti e acquisire i token di accesso usando MSAL.js
- Eseguire query sull'API STAC per individuare raccolte ed elementi
- Visualizzare riquadri raster in una mappa MAPLibre GL con intestazioni di autorizzazione
- Creare strati di mosaico senza problemi in intere collezioni
- Scaricare asset grezzi utilizzando token SAS
I modelli di codice funzionano con qualsiasi framework JavaScript moderno (React, Vue, Angular) o vanilla JavaScript. Le API GeoCatalog dispongono del supporto CORS completo, quindi è possibile chiamarle direttamente da localhost durante lo sviluppo, senza richiedere proxy.
È possibile scaricare e testare questo codice dal repository GitHub pubblico Microsoft Planetary Computer Pro.
Prerequisiti
- Un account Azure con una sottoscrizione attiva. Creare un account gratuito.
- Risorsa GeoCatalog distribuita con almeno una raccolta contenente elementi.
- L'identità utente deve disporre dell'accesso Lettore GeoCatalog (o superiore) alla risorsa GeoCatalog. Vedere Gestire l'accesso a una risorsa GeoCatalog.
- Node.js versione 18 o successiva.
Panoramica dell'architettura
Un'applicazione Web GeoCatalog tipica segue questa architettura:
Registrare l'applicazione in Microsoft Entra ID
Prima che l'applicazione Web possa autenticare gli utenti, registrarla in Microsoft Entra ID. Questo avvio rapido usa una registrazione Single Page Application (SPA), ideale per applicazioni JavaScript lato client e lo sviluppo locale. I modelli di integrazione API illustrati nei passaggi successivi funzionano con qualsiasi tipo di applicazione.
Annotazioni
Per le applicazioni di produzione con un server back-end, è consigliabile scegliere un tipo di registrazione diverso (Web, Nativo e così via). Per indicazioni sulla scelta dell'approccio appropriato per lo scenario, vedere Configurare l'autenticazione dell'applicazione .
Eseguire la registrazione come applicazione a pagina singola
- Passare a Microsoft Entra ID nel portale di Azure.
- Selezionare Registrazioni app nel pannello laterale.
- Seleziona Nuova registrazione.
- Immettere un nome per l'applicazione, ad esempio "App Web GeoCatalog".
- In Tipi di account supportati, selezionare solo gli account in questa directory organizzativa.
- In URI di reindirizzamento selezionare Applicazione a pagina singola (SPA) e immettere l'URL di sviluppo (ad esempio,
http://localhost:5173). - Selezionare Registrazione.
Dopo la registrazione, prendere nota dei valori seguenti nella pagina Panoramica :
- ID client dell'applicazione
- ID directory (tenant)
Per altre informazioni, vedere Registrazione dell'app di avvio rapido.
Concedere autorizzazioni API
L'applicazione deve disporre dell'autorizzazione per chiamare l'API GeoCatalog per conto degli utenti connessi:
- Nella registrazione dell'app selezionare Autorizzazioni> APIAggiungi un'autorizzazione.
- Selezionare API usate dall'organizzazione e cercare Azure Orbital Spatio.
- Selezionare Autorizzazioni delegate e controllare user_impersonation.
- Selezionare Aggiungi autorizzazioni.
- Se sei un amministratore, seleziona Concedi il consenso amministratore per conto di tutti gli utenti del tuo tenant.
Configurare l'applicazione
Per l'applicazione sono necessari i valori di configurazione seguenti. Il modo in cui si forniscono questi valori dipende dallo strumento di compilazione (variabili di ambiente, file di configurazione e così via):
| Configurazione | Value | Description |
|---|---|---|
| URL del catalogo | https://{name}.{region}.geocatalog.spatio.azure.com |
L'endpoint GeoCatalog |
| ID del locatario | Dalla registrazione dell'app | Il tenant Microsoft Entra |
| ID cliente | Dalla registrazione dell'app | ID client dell'applicazione |
| Ambito API | https://geocatalog.spatio.azure.com/.default |
Usare sempre questo valore esatto |
Installa le dipendenze
Installare Microsoft Authentication Library (MSAL) per le applicazioni browser e una libreria di mappe:
npm install @azure/msal-browser maplibre-gl
- @azure/msal-browser - Gestisce l'autenticazione OAuth 2.0 con Microsoft Entra ID
- maplibre-gl - Libreria di mappe open source per la visualizzazione dei riquadri
Suggerimento
Struttura del progetto: Gli esempi di codice in questa guida rapida sono funzioni autonome che è possibile organizzare come si preferisce. Modello comune:
-
auth.js: configurazione MSAL e funzioni token -
api.js: API STAC, API Tiler e funzioni del token SAS -
map.js: inizializzazione di MapLibre e gestione del livello delle piastrelle -
App.jsomain.js: collega tutto con l'interfaccia utente
Ogni funzione riceve le relative dipendenze (token di accesso, URL) come parametri, semplificando l'integrazione in qualsiasi framework o struttura del progetto.
Implementare l'autenticazione MSAL
Configurare MSAL per l'autenticazione del browser. L'esempio seguente illustra il modello di configurazione della chiave e di acquisizione dei token:
import { PublicClientApplication, InteractionRequiredAuthError } from '@azure/msal-browser';
// Configuration - replace with your values or load from environment/config
const msalConfig = {
auth: {
clientId: 'YOUR_CLIENT_ID',
authority: 'https://login.microsoftonline.com/YOUR_TENANT_ID',
redirectUri: window.location.origin,
},
cache: {
cacheLocation: 'sessionStorage',
storeAuthStateInCookie: false,
},
};
// Create MSAL instance
const msalInstance = new PublicClientApplication(msalConfig);
// GeoCatalog API scope - always use this exact value
const scopes = ['https://geocatalog.spatio.azure.com/.default'];
/**
* Acquire an access token for GeoCatalog API calls.
* Tries silent acquisition first, falls back to popup if needed.
*/
async function getAccessToken() {
const account = msalInstance.getActiveAccount() || msalInstance.getAllAccounts()[0];
if (!account) {
throw new Error('No authenticated account. Call login() first.');
}
try {
// Try silent token acquisition (uses cached token)
const result = await msalInstance.acquireTokenSilent({ account, scopes });
return result.accessToken;
} catch (error) {
// If silent fails (token expired), fall back to popup
if (error instanceof InteractionRequiredAuthError) {
const result = await msalInstance.acquireTokenPopup({ scopes });
return result.accessToken;
}
throw error;
}
}
/**
* Sign in the user via popup.
*/
async function login() {
const result = await msalInstance.loginPopup({ scopes });
msalInstance.setActiveAccount(result.account);
return result.account;
}
/**
* Sign out the user.
*/
function logout() {
msalInstance.logoutPopup();
}
API STAC: eseguire query su raccolte ed elementi
L'API STAC GeoCatalog fornisce endpoint per l'individuazione e l'esecuzione di query sui dati geospaziali. Tutte le richieste richiedono un'intestazione Authorization con un token Bearer ottenuto da Implementare l'autenticazione MSAL.
Elencare le raccolte
const API_VERSION = '2025-04-30-preview';
async function listCollections(accessToken, catalogUrl) {
const url = `${catalogUrl}/stac/collections?api-version=${API_VERSION}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(`Failed to list collections: ${response.statusText}`);
}
const data = await response.json();
return data.collections; // Array of STAC Collection objects
}
Elencare gli elementi in una raccolta
const API_VERSION = '2025-04-30-preview';
async function listItems(accessToken, catalogUrl, collectionId, limit = 10) {
const url = `${catalogUrl}/stac/collections/${collectionId}/items?limit=${limit}&api-version=${API_VERSION}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(`Failed to list items: ${response.statusText}`);
}
const data = await response.json();
return data.features; // Array of STAC Item objects
}
Eseguire ricerche tra raccolte
const API_VERSION = '2025-04-30-preview';
async function searchItems(accessToken, catalogUrl, searchParams) {
const url = `${catalogUrl}/stac/search?api-version=${API_VERSION}`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(searchParams),
});
if (!response.ok) {
throw new Error(`Search failed: ${response.statusText}`);
}
return await response.json();
}
// Example usage:
const results = await searchItems(token, catalogUrl, {
collections: ['my-collection'],
bbox: [-122.5, 37.5, -122.0, 38.0], // [west, south, east, north]
datetime: '2024-01-01/2024-12-31',
limit: 20,
});
URL delle tessere: Creazione di URL per la visualizzazione della mappa
L'API Tiler GeoCatalog serve i dati raster come riquadri della mappa. Creare URL di riquadri con il modello seguente:
Riquadri a singolo elemento
{catalogUrl}/data/collections/{collectionId}/items/{itemId}/tiles/{z}/{x}/{y}@1x.png
?api-version=2025-04-30-preview
&tileMatrixSetId=WebMercatorQuad
&assets=visual
Funzione generatore di URL tile
const API_VERSION = '2025-04-30-preview';
/**
* Build a tile URL template for a STAC item.
* Returns a URL with {z}/{x}/{y} placeholders for use with map libraries.
*/
function buildTileUrl(catalogUrl, collectionId, itemId, options = {}) {
const { assets = 'visual', colormap, rescale } = options;
const base = `${catalogUrl}/data/collections/${collectionId}/items/${itemId}/tiles/{z}/{x}/{y}@1x.png`;
const params = new URLSearchParams();
params.set('api-version', API_VERSION);
params.set('tileMatrixSetId', 'WebMercatorQuad');
params.set('assets', assets);
if (colormap) params.set('colormap_name', colormap);
if (rescale) params.set('rescale', rescale);
return `${base}?${params.toString()}`;
}
// Example usage:
const tileUrl = buildTileUrl(
'https://mygeocatalog.northcentralus.geocatalog.spatio.azure.com',
'aerial-imagery',
'image-001',
{ assets: 'visual' }
);
Parametri dei riquadri chiave
| Parametro | Obbligatorio | Description |
|---|---|---|
api-version |
Yes | Versione API (2025-04-30-preview) |
tileMatrixSetId |
Yes | Utilizzare WebMercatorQuad per le mappe web |
assets |
Yes | Nomi di asset di cui eseguire il rendering (ad esempio: visual, image) |
colormap_name |
NO | Mappa a colori denominata (esempio: viridis, terrain) |
rescale |
NO | Intervallo di valori per il ridimensionamento (ad esempio: 0,255) |
asset_bidx |
NO | Indici di banda (ad esempio: image\|1,2,3 per RGB) |
Annotazioni
Per le raccolte con immagini a quattro bande (ad esempio NAIP con RGB + NIR), usare asset_bidx=image|1,2,3 per selezionare solo le bande RGB. Il tiler non può codificare quattro bande come PNG.
Integrazione delle mappe: visualizzare i riquadri con MapLibre GL
Le librerie di mappe come MapLibre GL, Brochure e OpenLayers possono visualizzare riquadri raster. La sfida principale consiste nell'aggiungere intestazioni di autorizzazione alle richieste di riquadri, perché queste librerie recuperano direttamente i riquadri.
Esempio di MapLibre GL
MapLibre GL offre un'opzione transformRequest per inserire intestazioni:
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
// Store the current access token
let currentAccessToken = null;
function initializeMap(containerId, accessToken) {
currentAccessToken = accessToken;
const map = new maplibregl.Map({
container: containerId,
style: {
version: 8,
sources: {
osm: {
type: 'raster',
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution: '© OpenStreetMap contributors',
},
},
layers: [{ id: 'osm', type: 'raster', source: 'osm' }],
},
center: [0, 0],
zoom: 2,
// Add authorization header to tile requests
transformRequest: (url, resourceType) => {
// Only add auth for GeoCatalog tile requests
if (url.includes('geocatalog.spatio.azure.com') && currentAccessToken) {
return {
url,
headers: { 'Authorization': `Bearer ${currentAccessToken}` },
};
}
return { url };
},
});
return map;
}
function addTileLayer(map, tileUrl, bounds) {
// Remove existing layer and source if present
if (map.getLayer('data-layer')) {
map.removeLayer('data-layer');
}
if (map.getSource('data-tiles')) {
map.removeSource('data-tiles');
}
// Add tile source
map.addSource('data-tiles', {
type: 'raster',
tiles: [tileUrl],
tileSize: 256,
minzoom: 10, // Many aerial collections require zoom 10+
maxzoom: 18,
});
// Add tile layer
map.addLayer({
id: 'data-layer',
type: 'raster',
source: 'data-tiles',
});
// Zoom to bounds [west, south, east, north]
if (bounds) {
map.fitBounds([[bounds[0], bounds[1]], [bounds[2], bounds[3]]], { padding: 50 });
}
}
Importante
La transformRequest funzione viene chiamata per ogni richiesta di riquadro. Archiviare il token di accesso in una variabile a cui transformRequest è possibile accedere e aggiornarlo quando il token viene aggiornato.
Tessere mosaico: visualizzare immagini a livello di raccolta
Per visualizzare tutti gli elementi di una raccolta come livello continuo, registrare una ricerca a mosaico e usare l'ID ricerca restituito:
const API_VERSION = '2025-04-30-preview';
/**
* Register a mosaic search for a collection.
* Returns a search ID that can be used to fetch mosaic tiles.
*/
async function registerMosaic(catalogUrl, collectionId, accessToken) {
const url = `${catalogUrl}/data/mosaic/register?api-version=${API_VERSION}`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
collections: [collectionId],
}),
});
if (!response.ok) {
throw new Error(`Failed to register mosaic: ${response.statusText}`);
}
const data = await response.json();
// Note: API returns 'searchid' (lowercase), not 'searchId'
return data.searchid;
}
/**
* Build a mosaic tile URL template.
*/
function buildMosaicTileUrl(catalogUrl, searchId, collectionId, options = {}) {
const { assets = 'visual' } = options;
const base = `${catalogUrl}/data/mosaic/${searchId}/tiles/{z}/{x}/{y}@1x.png`;
const params = new URLSearchParams();
params.set('api-version', API_VERSION);
params.set('tileMatrixSetId', 'WebMercatorQuad');
params.set('collection', collectionId);
params.set('assets', assets);
return `${base}?${params.toString()}`;
}
Token SAS: scaricare asset non elaborati
L'API SAS fornisce token con tempo limitato per il download di file di asset non elaborati (GeoTIFFs, COG e altri file) direttamente da Archiviazione BLOB di Azure. Usare questa opzione quando sono necessari i file di origine originali anziché i riquadri di cui è stato eseguito il rendering.
Importante
I token SAS consentono solo i download nelle applicazioni browser. A causa dei criteri CORS di Archiviazione BLOB di Azure, i browser non possono leggere i dati BLOB tramite JavaScript fetch(). Vedere la sezione Limitazioni del browser .
Ottenere un token SAS
const API_VERSION = '2025-04-30-preview';
/**
* Get a SAS token for accessing assets in a collection.
* Returns a token string that can be appended to asset URLs.
*/
async function getCollectionSasToken(accessToken, catalogUrl, collectionId) {
const url = `${catalogUrl}/sas/token/${collectionId}?api-version=${API_VERSION}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(`Failed to get SAS token: ${response.statusText}`);
}
const data = await response.json();
return data.token; // SAS token string
}
Creare un URL di download firmato
/**
* Build a signed URL for downloading an asset.
* Appends the SAS token to the asset's href.
*/
function buildSignedAssetUrl(assetHref, sasToken) {
const separator = assetHref.includes('?') ? '&' : '?';
return `${assetHref}${separator}${sasToken}`;
}
// Example usage:
const sasToken = await getCollectionSasToken(accessToken, catalogUrl, 'my-collection');
const assetHref = item.assets['visual'].href;
const signedUrl = buildSignedAssetUrl(assetHref, sasToken);
Attivare un download di file
/**
* Trigger a browser download for an asset file.
* Works by creating a temporary anchor element.
*/
function downloadAsset(signedUrl, filename) {
const link = document.createElement('a');
link.href = signedUrl;
link.download = filename || 'download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// Example: Download an asset
downloadAsset(signedUrl, 'aerial-image.tif');
Limitazioni del browser
I token SAS funzionano diversamente nei browser rispetto al codice lato server.
| Caso d'uso | Browser | Lato server |
|---|---|---|
| Scaricare i file (l'utente seleziona il collegamento) | ✅ Funziona | ✅ Funziona |
Leggere i dati dei BLOB tramite fetch() |
❌ CORS bloccato | ✅ Funziona |
| Elaborare i pixel grezzi in JavaScript | ❌ Non possibile | ✅ Funziona |
I download del browser funzionano perché la navigazione (facendo clic sui collegamenti) bypassa CORS. Tuttavia, fetch() le richieste all'archiviazione BLOB di Azure vengono bloccate perché l'account di archiviazione non include l'origine dell'applicazione nei criteri CORS.
Se l'applicazione deve leggere ed elaborare i dati degli asset non elaborati nel browser, implementare un proxy lato server:
Annotazioni
Il codice seguente è un esempio semplificato per illustrare il modello proxy. Per le applicazioni di produzione, l'endpoint proxy deve autenticare le richieste, ad esempio inoltrando il token di connessione dell'utente o usando l'autenticazione della sessione, e verificare che l'utente sia autorizzato ad accedere alle risorse richieste.
// ❌ Browser: This fails due to CORS
const response = await fetch(signedUrl);
const data = await response.arrayBuffer(); // Error!
// ✅ Browser: Call your backend instead
const response = await fetch('/api/proxy-asset', {
method: 'POST',
body: JSON.stringify({ collectionId, itemId, assetName })
});
const data = await response.json(); // Works!
Il backend può recuperare il blob usando il SAS token e restituire i risultati elaborati.
Considerazioni sullo sviluppo
Supporto CORS
Le API GeoCatalog includono il supporto CORS completo con Access-Control-Allow-Origin: *. Le applicazioni basate su browser possono effettuare richieste dirette a GeoCatalog da qualsiasi origine, incluso http://localhost durante lo sviluppo. Non è necessario alcun proxy o soluzione alternativa.
L'API consente l'intestazione Authorization nelle richieste CORS, quindi le chiamate autenticate fetch() funzionano direttamente dal browser JavaScript.
Scelta del metodo di accesso ai dati corretto
| Metodo | Browser fetch() |
Download del browser | Lato server | Ideale per |
|---|---|---|---|---|
| Tiler API | ✅ Supporto completo | ✅ Sì | ✅ Sì | Visualizzazione mappa |
| Token SAS | ❌ CORS bloccato | ✅ Sì | ✅ Sì | Download di file non elaborati |
API Tiler: usare per la visualizzazione di immagini nelle mappe. Restituisce i riquadri PNG o WebP sottoposti a rendering con supporto CORS completo. Vedere URL riquadro e Integrazione mappa.
Token SAS: usare per scaricare i file di origine (GeoTIFFs, COGs). I download del browser funzionano, ma
fetch()è bloccato dai criteri CORS di Azure Blob Storage. Vedere Token SAS (Token di firma di accesso condiviso) per informazioni dettagliate e soluzioni alternative.
Aggiornamento token
I token di accesso scadono, in genere dopo un'ora. L'applicazione deve:
- Gestire gli errori 401 acquisendo un nuovo token.
- Usare l'acquisizione di token silenziosa di MSAL, che aggiorna automaticamente i token scaduti.
- Aggiorna il riferimento al token usato dall'oggetto
transformRequestdella mappa.
Gestione degli errori
Gestire scenari di errore comuni:
| Stato HTTP | Motivo | Soluzione |
|---|---|---|
| 401 | Token scaduto o non valido | Aggiornare il token di accesso |
| 404 | Elemento o raccolta non trovato | Verificare che gli ID esistano |
| 424 | Riquadro esterno all'estensione dei dati | Previsto - gestire senza problemi |
Risoluzione dei problemi
| Errore | Motivo | Soluzione |
|---|---|---|
| "AADSTS50011: mancata corrispondenza dell'URL di risposta" | L'URI di reindirizzamento nel codice non corrisponde alla registrazione dell'ID Microsoft Entra | Aggiungi l'URL di sviluppo (ad esempio, http://localhost:3000) come URI di reindirizzamento SPA nella registrazione dell'app. |
| Errore "Ambito non valido" | Uso dell'URL GeoCatalog anziché dell'ambito API | Usare https://geocatalog.spatio.azure.com/.default come ambito |
| Errore 401 Autorizzazione mancante sulle richieste riquadri | La libreria di mappe non include le intestazioni delle autorizzazioni | Usare transformRequest (MapLibre) per aggiungere il token Bearer; assicurarsi che il token sia aggiornato. |
| I riquadri non sono allineati alla mappa di base | Set di matrici riquadro errato | Usare tileMatrixSetId=WebMercatorQuad per la proiezione Web Mercator (EPSG:3857) |
| "Non è stato possibile decodificare l'immagine" | Nome dell'asset errato, immagini multibanda o intervallo di dati esterni | Verificare item_assets per la presenza di nomi validi; usare asset_bidx=image\|1,2,3 per RGB; si prevedono 404/424 al di fuori della copertura |