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.
Distribuire API Web ASP.NET Core protette con Microsoft.Identity.Web dietro i gateway API di Azure e proxy inverso, tra cui Gestione API di Azure, Frontdoor di Azure e gateway applicazione di Azure.
Informazioni sui requisiti del gateway
Quando si distribuiscono API protette dietro i gateway, è necessario gestire diversi problemi:
- Intestazioni inoltrate - Mantenere il contesto di richiesta originale (schema, host, IP)
- Convalida dei token : assicurarsi che le attestazioni del gruppo di destinatari corrispondano agli URL del gateway
- Configurazione CORS : gestire correttamente le richieste tra le origini
- Endpoint di salute - fornisce controlli di integrità non autenticati
- Routing basato sul percorso - Supportare i prefissi di percorso a livello di gateway
- Terminazione SSL/TLS : gestire correttamente HTTPS quando il gateway termina SSL
Esaminare gli scenari comuni del gateway
Scegliere un gateway in base alle esigenze. Le sezioni seguenti descrivono i servizi gateway Azure più comuni per le API protette.
Gestione API di Azure
Caso d'uso: Gateway API aziendale con criteri, limitazione della frequenza, trasformazione
Architettura:
Client → Microsoft Entra ID → Token
Client → APIM (apim.azure-api.net) → Backend API (app.azurewebsites.net)
Considerazioni chiave:
- Le politiche di gestione delle API possono convalidare i token JWT prima dell'inoltro al backend.
- L'API back-end convalida ancora i token
- L'attestazione destinatario deve corrispondere all'URL di Gestione API o all'URL backend (configurare di conseguenza)
Frontdoor di Azure
Caso d'uso: Bilanciamento del carico globale, rete CDN, protezione DDoS
Architettura:
Client → Microsoft Entra ID → Token
Client → Front Door (azurefd.net) → Backend API (regional endpoints)
Considerazioni chiave:
- Front Door inoltra le richieste con
X-Forwarded-*intestazioni - Terminazione SSL/TLS di Front Door
- La convalida del gruppo di destinatari dei token richiede la configurazione
gateway applicazione di Azure
Caso d'uso: Bilanciamento del carico regionale, WAF, routing basato sul percorso
Architettura:
Client → Microsoft Entra ID → Token
Client → Application Gateway → Backend API (multiple instances)
Considerazioni chiave:
- Integrazione di Web application firewall (WAF)
- Regole di routing basate sul percorso
- I probe di integrità back-end necessitano di endpoint non autenticati
Configurare modelli comuni
Applicare questi modelli di configurazione per assicurarsi che l'API protetta funzioni correttamente dietro qualsiasi gateway.
1. Middleware delle intestazioni inoltrate
Configurare sempre il middleware delle intestazioni inoltrate quando si è dietro un gateway di rete. Il codice seguente registra il middleware e lo imposta per l'esecuzione prima dell'autenticazione:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
// Configure forwarded headers BEFORE authentication
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto |
ForwardedHeaders.XForwardedHost;
// Clear known networks/proxies to accept forwarded headers from any source
// (Azure infrastructure will be the proxy)
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
// Limit to specific headers if needed
options.ForwardedForHeaderName = "X-Forwarded-For";
options.ForwardedProtoHeaderName = "X-Forwarded-Proto";
options.ForwardedHostHeaderName = "X-Forwarded-Host";
});
// Add authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
var app = builder.Build();
// USE forwarded headers BEFORE authentication middleware
app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();
app.Run();
Il middleware delle intestazioni inoltrate riveste un ruolo critico perché:
- Mantiene l'indirizzo IP del client originale per la registrazione
- Assicura che
HttpContext.Request.Schemerifletta lo schema HTTPS originale - Fornisce l'intestazione corretta
Hostper gli URL di reindirizzamento e la convalida dei token
2. Configurazione del gruppo di destinatari dei token
Opzione A: Accettare sia gli URL del gateway che del back-end
Aggiungere più gruppi di destinatari validi nella appsettings.json configurazione:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id",
"Audience": "api://your-client-id",
"TokenValidationParameters": {
"ValidAudiences": [
"api://your-client-id",
"https://your-backend.azurewebsites.net",
"https://your-apim.azure-api.net"
]
}
}
}
In alternativa, configurare più gruppi di destinatari a livello di codice in Program.cs:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
// Customize token validation to accept multiple audiences
builder.Services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
var existingValidation = options.TokenValidationParameters.AudienceValidator;
options.TokenValidationParameters.AudienceValidator = (audiences, token, parameters) =>
{
var validAudiences = new[]
{
"api://your-client-id",
"https://your-backend.azurewebsites.net",
"https://your-apim.azure-api.net",
builder.Configuration["AzureAd:ClientId"] // Also accept ClientId
};
return audiences.Any(a => validAudiences.Contains(a, StringComparer.OrdinalIgnoreCase));
};
});
Opzione B: Riscrivere l'audience nei criteri di APIM
Configurare Gestione delle API per convalidare la dichiarazione del pubblico prima di inoltrarlo al back-end.
<policies>
<inbound>
<validate-jwt header-name="Authorization" failed-validation-httpcode="401">
<openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>api://your-client-id</audience>
</audiences>
</validate-jwt>
<!-- Optionally modify token claims for backend -->
<set-header name="X-Gateway-Validated" exists-action="override">
<value>true</value>
</set-header>
</inbound>
</policies>
3. Configurazione dell'endpoint di salute
I gateway richiedono endpoint di controllo dell'integrità non autenticati per i probe. Eseguire il mapping di un endpoint di monitoraggio prima del middleware di autenticazione per bypassare la convalida del token.
var app = builder.Build();
// Health endpoint BEFORE authentication middleware
app.MapGet("/health", () => Results.Ok(new { status = "healthy" }))
.AllowAnonymous();
app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();
// Protected endpoints require authentication
app.MapControllers();
app.Run();
In alternativa, usare il framework predefinito ASP.NET Core controlli di integrità per la creazione di report sull'integrità più avanzati:
using Microsoft.Extensions.Diagnostics.HealthChecks;
builder.Services.AddHealthChecks()
.AddCheck("api", () => HealthCheckResult.Healthy());
var app = builder.Build();
app.MapHealthChecks("/health").AllowAnonymous();
app.MapHealthChecks("/ready").AllowAnonymous();
app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
4. Configurazione CORS dietro i gateway
Quando si usano Frontdoor di Azure o API Management con applicazioni frontend, configurare CORS per consentire le richieste provenienti dalle origini del gateway.
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowGateway", policy =>
{
policy.WithOrigins(
"https://your-apim.azure-api.net",
"https://your-frontend.azurefd.net",
"https://your-app.azurewebsites.net"
)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials(); // If using cookies
});
});
var app = builder.Build();
app.UseForwardedHeaders();
app.UseCors("AllowGateway");
app.UseAuthentication();
app.UseAuthorization();
app.Run();
Importante
È necessario configurare CORS dopo le intestazioni inoltrate e prima dell'autenticazione.
Eseguire l'integrazione con Gestione API di Azure
Questa sezione fornisce la configurazione completa per la distribuzione di un'API protetta dietro Gestione API di Azure.
Configurare l'API back-end
Configurare le intestazioni inoltrate e l'autenticazione Microsoft Entra ID in Program.cs:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Forwarded headers for APIM
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.All;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
// Authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllers();
var app = builder.Build();
// Middleware order matters
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Aggiungere la configurazione di Microsoft Entra a appsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-backend-api-client-id",
"Audience": "api://your-backend-api-client-id"
}
}
Aggiungere una policy di ingresso in API Management per la convalida JWT
Definire un criterio in ingresso che convalida il token JWT, applica la limitazione della frequenza e inoltra la richiesta al back-end:
<policies>
<inbound>
<base />
<!-- Validate JWT token -->
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized">
<openid-config url="https://login.microsoftonline.com/{your-tenant-id}/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>api://your-backend-api-client-id</audience>
</audiences>
<issuers>
<issuer>https://login.microsoftonline.com/{your-tenant-id}/v2.0</issuer>
</issuers>
<required-claims>
<claim name="scp" match="any">
<value>access_as_user</value>
</claim>
</required-claims>
</validate-jwt>
<!-- Rate limiting -->
<rate-limit calls="100" renewal-period="60" />
<!-- Forward original host header -->
<set-header name="X-Forwarded-Host" exists-action="override">
<value>@(context.Request.OriginalUrl.Host)</value>
</set-header>
<!-- Forward to backend -->
<set-backend-service base-url="https://your-backend.azurewebsites.net" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
Configurare le impostazioni api di Gestione API
Usare i seguenti valori denominati e le impostazioni dell'API per completare la configurazione di APIM:
Valori denominati (per la riutilizzabilità):
-
tenant-id: ID del tenant Microsoft Entra -
backend-api-client-id: ID client del backend API -
backend-base-url:https://your-backend.azurewebsites.net
Impostazioni API:
-
Suffisso dell'URL API:
/api(prefisso del percorso opzionale) - URL del servizio Web: impostare tramite policy usando valori assegnati
- Sottoscrizione obbligatoria: Sì (aggiunge un altro livello di sicurezza)
Configurare l'applicazione client
Le app client richiedono token per l'API back-end, non APIM. Il codice seguente acquisisce un token e chiama l'API tramite l'endpoint APIM.
// Client app requests token
var result = await app.AcquireTokenSilent(
scopes: new[] { "api://your-backend-api-client-id/access_as_user" },
account)
.ExecuteAsync();
// Call APIM URL with token
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", result.AccessToken);
// Add APIM subscription key
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "your-subscription-key");
var response = await client.GetAsync("https://your-apim.azure-api.net/api/weatherforecast");
Integrazione con Frontdoor di Azure
Configurare l'API protetta per la distribuzione globale dietro Frontdoor di Azure.
Configurare l'API back-end
Configurare le intestazioni inoltrate per Frontdoor di Azure in Program.cs:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
// Configure for Azure Front Door
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto |
ForwardedHeaders.XForwardedHost;
// Accept headers from any source (Azure Front Door)
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
// Front Door specific headers
options.ForwardedForHeaderName = "X-Forwarded-For";
options.ForwardedProtoHeaderName = "X-Forwarded-Proto";
});
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
var app = builder.Build();
app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Configurare le origini di Frontdoor
Completare i passaggi seguenti nel portale di Azure per configurare l'origine di Frontdoor:
- Creare un profilo Front Door
- Aggiungere un gruppo di origine con le istanze dell'API back-end
- Configurare le sonde di salute per l'endpoint
/health - Impostare solo l'inoltro HTTPS
- Abilitare i criteri WAF (facoltativo)
Impostazioni della sonda di monitoraggio:
-
Percorso:
/health - Protocollo: HTTPS
- Metodo: GET
- Intervallo: 30 secondi
Gestire più aree
Quando si effettua la distribuzione in più aree dietro Front Door, aggiungere la consapevolezza delle regioni per la registrazione e la diagnostica.
// Add region awareness for logging/diagnostics
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
app.Use(async (context, next) =>
{
// Log the actual client IP and region
var clientIp = context.Connection.RemoteIpAddress?.ToString();
var forwardedFor = context.Request.Headers["X-Forwarded-For"].ToString();
var frontDoorId = context.Request.Headers["X-Azure-FDID"].ToString();
// Add to logger scope or response headers
context.Response.Headers.Add("X-Served-By-Region",
builder.Configuration["Region"] ?? "unknown");
await next();
});
Convalidare i token con Frontdoor
Se i client richiedono token con ambito all'URL di Frontdoor, aggiungerli all'elenco di gruppi di destinatari validi:
builder.Services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.TokenValidationParameters.ValidAudiences = new[]
{
"api://your-backend-api-client-id",
"https://your-frontend.azurefd.net", // Front Door URL
builder.Configuration["AzureAd:ClientId"]
};
});
Eseguire l'integrazione con il gateway applicazione di Azure
Configurare l'API protetta dietro gateway applicazione di Azure con il supporto di Web application firewall (WAF).
Configurare l'API back-end
Configurare le intestazioni inoltrate per il gateway delle applicazioni in Program.cs:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
// Application Gateway uses standard forwarded headers
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddHealthChecks();
var app = builder.Build();
// Health endpoint for Application Gateway probes
app.MapHealthChecks("/health").AllowAnonymous();
app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Configurare le impostazioni del gateway dell'applicazione
Impostare le seguenti impostazioni di backend, sonda di integrità e WAF nel portale di Azure:
Impostazioni back-end:
- Protocollo: HTTPS (scelta consigliata) o HTTP
- Port: 443 o 80
- Sovrascrivere il percorso back-end: No (a meno che necessario)
-
Probe personalizzato: Sì, puntando a
/health
Sonda di integrità:
- Protocollo: HTTPS o HTTP
- Host: lasciare l'impostazione predefinita o specificare
-
Percorso:
/health - Intervallo: 30 secondi
- Soglia di allerta: 3
Politica WAF:
- Abilitare WAF con il set di regole OWASP 3.2
-
Importante: assicurarsi che i token JWT nelle
Authorizationintestazioni non siano bloccati - Potrebbe essere necessario creare esclusioni WAF per
RequestHeaderNamescontenere "Autorizzazione"
Configurare il routing basato sul percorso
Quando si usano regole di routing basate sul percorso, configurare l'API back-end per gestire il prefisso del percorso:
// Backend API should work regardless of path prefix
var app = builder.Build();
// Option 1: Use path base (if gateway adds prefix)
app.UsePathBase("/api/v1");
// Option 2: Configure routing explicitly
app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Regola del gateway delle applicazioni:
-
Percorso:
/api/v1/* - Destinazione backend: pool backend
- Impostazioni back-end: usare le impostazioni configurate
Risolvere i problemi comuni
Usare queste soluzioni per risolvere i problemi più comuni durante la distribuzione di API protette dietro i gateway.
Problema: 401 Non autorizzato dopo la distribuzione dietro a un gateway
Sintomi:
- L'API funziona in locale ma restituisce un errore 401 dietro il gateway.
- Il token sembra valido quando decodificato in jwt.ms
Possibili cause:
Mancata corrispondenza della dichiarazione dei destinatari
# Check token audience # Decode token and verify 'aud' claim matches one of: # - api://your-client-id # - https://your-backend.azurewebsites.net # - https://your-gateway-urlMiddleware per intestazioni inoltrate mancanti
// Ensure this is BEFORE authentication app.UseForwardedHeaders(); app.UseAuthentication();Problemi di reindirizzamento HTTPS
// If gateway terminates SSL, may need to disable or configure carefully if (!app.Environment.IsDevelopment()) { app.UseHttpsRedirection(); }
Soluzione:
- Abilitare la registrazione di debug per visualizzare i dettagli di convalida dei token
- Aggiungere più gruppi di destinatari validi nella convalida del token
- Verificare che le intestazioni
X-Forwarded-*vengano inoltrate dal gateway
Problema: i probe di integrità hanno esito negativo
Sintomi:
- Il gateway contrassegna il back-end come non funzionante
- L'endpoint di integrità restituisce 401
Soluzione:
Verificare che l'endpoint di integrità venga eseguito prima del middleware di autenticazione:
// Ensure health endpoint is BEFORE authentication
app.MapHealthChecks("/health").AllowAnonymous();
// Alternative: Use custom middleware
app.Map("/health", healthApp =>
{
healthApp.Run(async context =>
{
context.Response.StatusCode = 200;
await context.Response.WriteAsync("healthy");
});
});
app.UseAuthentication(); // Health endpoint bypasses this
Problema: errori CORS dietro Frontdoor
Sintomi:
- Le richieste OPTIONS preliminari hanno esito negativo
- La console del browser mostra gli errori CORS
Soluzione:
Aggiungere le origini frontdoor e front-end ai criteri CORS:
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins(
"https://your-frontend.azurefd.net",
"https://your-app.com"
)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
var app = builder.Build();
app.UseForwardedHeaders();
app.UseCors(); // Before authentication
app.UseAuthentication();
app.UseAuthorization();
Problema: avvisi sull'intestazione inoltrata nei log
Sintomi:
Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware: Unknown proxy
Soluzione:
Reimpostare le configurazioni delle reti note e dei proxy per accettare le intestazioni inoltrate dall'infrastruttura di Azure.
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
// Clear known networks to accept from any proxy
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
// Or explicitly add Azure IP ranges (more secure but complex)
// options.KnownProxies.Add(IPAddress.Parse("20.x.x.x"));
});
Problema: APIM restituisce 401 ma il backend restituisce 200
Sintomi:
- Il token è valido per il back-end
- Il criterio di Gestione API
validate-jwtfallisce
Soluzione:
Verificare che il gruppo di destinatari dei criteri di Gestione API corrisponda al gruppo di destinatari del token:
<validate-jwt header-name="Authorization">
<openid-config url="https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration" />
<audiences>
<!-- Must match the 'aud' claim in your token -->
<audience>api://your-backend-api-client-id</audience>
</audiences>
</validate-jwt>
Problema: conflitti tra più schemi di autenticazione
Sintomi:
- Uso sia del bearer JWT che di altri schemi
- Schema errato selezionato
Soluzione:
Specificare lo schema di autenticazione in modo esplicito nel controller:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
.AddScheme<MyCustomOptions, MyCustomHandler>("CustomScheme", options => {});
// In controller, specify scheme explicitly
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class WeatherForecastController : ControllerBase
{
// ...
}
Seguire le migliori pratiche
Applicare queste procedure per creare una distribuzione api sicura e resiliente dietro i gateway.
1. Difesa in profondità
Convalidare sempre i token nell'API back-end, anche se il gateway li convalida:
// Gateway validates token (APIM policy)
// Backend ALSO validates token (Microsoft.Identity.Web)
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
La configurazione del gateway può essere modificata e i token possono essere riprodotti. La difesa avanzata è fondamentale per la sicurezza.
2. Usare le identità gestite per la comunicazione da gateway a back-end
Se il gateway chiama il back-end con la propria identità, configurare il back-end per accettare sia token utente che token di identità gestiti:
// Backend accepts both user tokens and gateway's managed identity
builder.Services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.TokenValidationParameters.ValidAudiences = new[]
{
"api://backend-api-client-id", // User tokens
"https://management.azure.com" // Managed identity tokens (if applicable)
};
});
3. Monitorare le metriche del gateway
Tenere traccia di queste metriche chiave per mantenere la visibilità sulla distribuzione del gateway:
- 401/403 percentuali di errore
- Errori di convalida dei token
- Errori della sonda di integrità
- Intestazioni inoltrate (per il debugging)
4. Utilizzare Application Insights
Aggiungere i dati di telemetria di Application Insights per registrare le proprietà delle richieste specifiche del gateway:
builder.Services.AddApplicationInsightsTelemetry();
// Log custom properties
app.Use(async (context, next) =>
{
var telemetry = context.RequestServices.GetRequiredService<TelemetryClient>();
telemetry.TrackEvent("ApiRequest", new Dictionary<string, string>
{
["ForwardedFor"] = context.Request.Headers["X-Forwarded-For"],
["OriginalHost"] = context.Request.Headers["X-Forwarded-Host"],
["Gateway"] = "APIM" // or "FrontDoor", "AppGateway"
});
await next();
});
5. Separare la salute da disponibile
Usare endpoint distinti per l'attività (è il servizio in esecuzione?) e la prontezza (il servizio può accettare il traffico?) verifiche:
// Health: Is the service running?
app.MapGet("/health", () => Results.Ok()).AllowAnonymous();
// Ready: Can the service accept traffic?
app.MapHealthChecks("/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("ready")
}).AllowAnonymous();
builder.Services.AddHealthChecks()
.AddCheck("database", () => /* check DB */ , tags: new[] { "ready" })
.AddCheck("cache", () => /* check cache */ , tags: new[] { "ready" });
6. Documentare la configurazione del gateway
Creare una pagina README o wiki che documenta:
- Quali gateway sono in uso
- Aspettative dei destinatari dei token
- Configurazione CORS
- Endpoint delle probe di stato
- Configurazione delle intestazioni inoltrate
- Procedure di rollback di emergenza
Creare un esempio completo con Gestione API di Azure
Questa sezione fornisce un esempio completo e pronto per la produzione di un'API ASP.NET Core dietro Gestione API di Azure con autenticazione Microsoft Entra ID.
Back-end API (ASP.NET Core)
L'Program.cs seguente configura le intestazioni inoltrate, l'autenticazione Microsoft Entra, i controlli di integrità e Application Insights:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Forwarded headers for APIM
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.All;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
// Authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph()
.AddInMemoryTokenCaches();
// Application Insights
builder.Services.AddApplicationInsightsTelemetry();
// Health checks
builder.Services.AddHealthChecks();
builder.Services.AddControllers();
var app = builder.Build();
// Health endpoint (unauthenticated)
app.MapHealthChecks("/health").AllowAnonymous();
// Middleware order is critical
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Aggiungere la configurazione di Microsoft Entra e di Application Insights seguente in appsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "backend-api-client-id",
"Audience": "api://backend-api-client-id"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.Identity.Web": "Debug"
}
},
"ApplicationInsights": {
"ConnectionString": "your-connection-string"
}
}
Il seguente controller richiede l'autenticazione e registra le intestazioni inoltrate per il debug.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web.Resource;
[Authorize]
[ApiController]
[Route("[controller]")]
[RequiredScope("access_as_user")]
public class WeatherForecastController : ControllerBase
{
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IActionResult Get()
{
// Log forwarded headers for debugging
var forwardedFor = HttpContext.Request.Headers["X-Forwarded-For"];
var forwardedHost = HttpContext.Request.Headers["X-Forwarded-Host"];
_logger.LogInformation(
"Request from {ForwardedFor} via {ForwardedHost}",
forwardedFor,
forwardedHost);
return Ok(new[] { "Weather", "Forecast", "Data" });
}
}
Configurazione di API Management
La politica di ricezione seguente convalida i token JWT, applica la limitazione della frequenza, inoltra le intestazioni e configura CORS.
<policies>
<inbound>
<base />
<!-- Rate limiting per subscription -->
<rate-limit-by-key calls="100" renewal-period="60"
counter-key="@(context.Subscription.Id)" />
<!-- Validate JWT -->
<validate-jwt header-name="Authorization"
failed-validation-httpcode="401"
failed-validation-error-message="Unauthorized">
<openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>api://backend-api-client-id</audience>
</audiences>
<issuers>
<issuer>https://login.microsoftonline.com/{tenant-id}/v2.0</issuer>
</issuers>
<required-claims>
<claim name="scp" match="any">
<value>access_as_user</value>
</claim>
</required-claims>
</validate-jwt>
<!-- Forward headers -->
<set-header name="X-Forwarded-Host" exists-action="override">
<value>@(context.Request.OriginalUrl.Host)</value>
</set-header>
<set-header name="X-Forwarded-Proto" exists-action="override">
<value>@(context.Request.OriginalUrl.Scheme)</value>
</set-header>
<!-- Backend URL -->
<set-backend-service base-url="https://your-backend.azurewebsites.net" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
<!-- Add CORS headers if needed -->
<cors>
<allowed-origins>
<origin>https://your-frontend.com</origin>
</allowed-origins>
<allowed-methods>
<method>GET</method>
<method>POST</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
</cors>
</outbound>
<on-error>
<base />
</on-error>
</policies>