Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Разверните ASP.NET Core веб-API, защищенные Microsoft.Identity.Web, за шлюзами API Azure и обратными прокси-серверами, включая Azure API Management (APIM), Azure Front Door и Шлюз приложений Azure.
Общие сведения о требованиях к шлюзу
При развертывании защищенных API за шлюзами необходимо учитывать несколько аспектов.
- Перенаправленные заголовки — сохранять исходный контекст запроса (схема, хост, IP-адрес)
- Проверка токенов - Убедитесь, что требования аудитории соответствуют URL-адресам шлюза
- Конфигурация CORS - Правильно обрабатывать кросс-оригинальные запросы
- Точки проверки состояния — Предоставление проверок состояния без аутентификации
- Маршрутизация на основе пути — поддержка префиксов пути на уровне шлюза
- Завершение SSL/TLS — правильная обработка HTTPS при завершении SSL-сессии на шлюзе
Обзор распространенных сценариев использования шлюза
Выберите шлюз на основе ваших требований. В следующих разделах описаны наиболее распространенные службы шлюза Azure для защищенных API.
Azure API Management (APIM)
Вариант использования: Корпоративный шлюз API с политиками, ограничением скорости, преобразованием
Архитектура.
Client → Microsoft Entra ID → Token
Client → APIM (apim.azure-api.net) → Backend API (app.azurewebsites.net)
Основные рекомендации:
- Политики APIM могут проверять JWT-токены перед пересылкой в бэкэнд
- Серверный API всё ещё проверяет токены.
- Утверждение аудитории должно соответствовать URL-адресу APIM или внутреннему URL-адресу (настройте соответствующим образом)
Azure Front Door
Вариант использования: Глобальная балансировка нагрузки, CDN, защита от атак DDoS
Архитектура.
Client → Microsoft Entra ID → Token
Client → Front Door (azurefd.net) → Backend API (regional endpoints)
Основные рекомендации:
- Front Door пересылает запросы с
X-Forwarded-*заголовками - Завершение SSL/TLS в Front Door
- Проверка аудитории токенов нуждается в настройке
Шлюз приложений Azure
Вариант использования: Региональная балансировка нагрузки, WAF, маршрутизация на основе пути
Архитектура.
Client → Microsoft Entra ID → Token
Client → Application Gateway → Backend API (multiple instances)
Основные рекомендации:
- интеграция Межсетевого экрана веб-приложений (WAF)
- Правила маршрутизации на основе пути
- Для проверки работоспособности серверной части требуются неаутентифицированные конечные точки.
Настройка распространенных шаблонов
Примените эти шаблоны конфигурации, чтобы обеспечить правильную работу защищенного API за любым шлюзом.
1. Промежуточное ПО для обработки перенаправленных заголовков
Всегда настраивайте посредник перенаправленных заголовков, находясь за шлюзом. Следующий код регистрирует ПО промежуточного слоя и задает его для запуска перед проверкой подлинности:
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();
Промежуточная функция пересылки заголовков критически важна, так как она:
- Сохраняет исходный IP-адрес клиента для ведения журнала
-
HttpContext.Request.SchemeГарантирует отражение исходной схемы HTTPS - Предоставляет правильный
Hostзаголовок для URL-адресов перенаправления и валидации токенов
2. Настройка аудитории токенов
Вариант A: Принимает URL-адреса шлюза и серверной инфраструктуры
Добавьте несколько допустимых аудиторий в конфигурацию appsettings.json.
{
"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"
]
}
}
}
Кроме того, настройте несколько аудиторий программным способом в 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));
};
});
Вариант B. Перезапись аудитории в политике APIM
Настройте APIM для проверки претензии аудитории перед пересылкой на серверную часть.
<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. Конфигурация конечной точки работоспособности
Шлюзы требуют неаутентифицированные конечные точки проверки состояния для проб. Сопоставьте точку проверки состояния системы перед промежуточным ПО проверки подлинности для обхода проверки токенов.
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();
Кроме того, используйте встроенную платформу проверки работоспособности ASP.NET Core для более подробных отчетов о работоспособности:
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. Конфигурация CORS за шлюзами
При использовании Azure Front Door или APIM с интерфейсными приложениями настройте CORS для разрешения запросов из источников шлюза:
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();
Важно
CORS необходимо настроить после переадресации заголовков и перед проверкой подлинности.
Интеграция с Azure API Management
В этом разделе представлена полная конфигурация для развертывания защищенного API посредством Azure API Management.
Настройка серверного API
Настройте перенаправленные заголовки и проверку подлинности Microsoft Entra ID в 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();
Добавьте конфигурацию Microsoft Entra в 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"
}
}
Добавить политику входящего трафика APIM для проверки JWT
Определите политику входящего трафика, которая проверяет токен JWT, применяет ограничение скорости и перенаправляет запрос на серверную часть:
<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>
Настройка параметров APIM
Используйте следующие именованные значения и параметры API для завершения конфигурации APIM:
Именованные значения (для повторного использования):
-
tenant-id: идентификатор клиента Microsoft Entra -
backend-api-client-id: идентификатор клиента внутреннего API -
backend-base-url:https://your-backend.azurewebsites.net
Параметры API:
-
Суффикс URL-адреса API:
/api(необязательный префикс пути) - URL-адрес веб-службы: задается политикой с использованием именованных значений
- Требуется подписка: Да (добавляет еще один уровень безопасности)
Настройка клиентского приложения
Клиентские приложения запрашивают токены для серверного API, а не для APIM. Следующий код получает маркер и вызывает API через конечную точку 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");
Интеграция с Azure Front Door
Настройте защищенный API для глобального распространения через Azure Front Door.
Настройка серверного API
Настройте перенаправленные заголовки для Azure Front Door в 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();
Настройка источников Front Door
Выполните следующие действия на портале Azure, чтобы настроить источник Front Door:
- Создание профиля Azure Front Door
- Добавьте группу источников с вашими экземплярами API бэкенда
- Настройка проб работоспособности в конечной точке
/health - Установить только перенаправление HTTPS
- Включение политики WAF (необязательно)
Настройки проверки работоспособности:
-
Путь:
/health. - Протокол: HTTPS
- Метод : GET
- Интервал: 30 секунд
Управление несколькими регионами
При развертывании в нескольких регионах с использованием Front Door настройте региональную привязку для журналирования и диагностики.
// 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();
});
Проверка токенов с помощью Front Door
Если клиенты запрашивают токены, указанные в контексте URL-адреса Front Door, добавьте его в список допустимых аудиторий.
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"]
};
});
Интеграция с Шлюзом приложений Azure
Настройте защищенный API за Шлюз приложений Azure с поддержкой Брандмауэр веб-приложений (WAF).
Настройка серверного API
Настройка перенаправленных заголовков для шлюза приложений в 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();
Настройка параметров шлюза приложений
Задайте следующие параметры серверной части, пробы работоспособности и WAF на портале Azure:
Параметры серверной части:
- Протокол: HTTPS (рекомендуется) или HTTP
- Порт: 443 или 80
- Переопределение пути бэкэнда: нет (если не требуется)
-
Пользовательский зонд: да, указывает на
/health
Проба работоспособности:
- Протокол: HTTPS или HTTP
- Хост: оставьте значение по умолчанию или задайте своё.
-
Путь:
/health. - Интервал: 30 секунд
- Порог нездорового состояния: 3
Политика WAF:
- Включение WAF с помощью набора правил OWASP 3.2
-
Важно. Убедитесь, что маркеры JWT в
Authorizationзаголовках не блокируются - Возможно, потребуется создать исключения WAF для
RequestHeaderNamesсодержащих "Авторизация"
Настройка маршрутизации на основе пути
При использовании правил маршрутизации на основе путей настройте внутренний API для обработки префикса пути:
// 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();
Правило шлюза приложений:
-
Путь:
/api/v1/*. - Целевой объект бэкенда: пул серверов
- Параметры серверной части: использование настроенных параметров
Устранение распространенных неполадок
Используйте эти решения для устранения наиболее распространенных проблем при развертывании защищенных API за шлюзами.
Проблема: 401 Неавторизовано после развертывания за шлюзом
Симптомы
- API работает локально, но возвращает 401 за шлюзом
- Токен кажется допустимым при декодировании на сайте jwt.ms
Возможные причины:
Несоответствие утверждений аудитории
# Check token audience # Decode token and verify 'aud' claim matches one of: # - api://your-client-id # - https://your-backend.azurewebsites.net # - https://your-gateway-urlОтсутствует промежуточное ПО для перенаправленных заголовков
// Ensure this is BEFORE authentication app.UseForwardedHeaders(); app.UseAuthentication();Проблемы с перенаправлением HTTPS
// If gateway terminates SSL, may need to disable or configure carefully if (!app.Environment.IsDevelopment()) { app.UseHttpsRedirection(); }
Solution:
- Включите ведение журнала отладки, чтобы просмотреть сведения о проверке токенов.
- Добавление нескольких допустимых аудиторий в проверке токенов
- Убедитесь, что заголовки
X-Forwarded-*перенаправляются шлюзом.
Проблема: сбой зондов проверки работоспособности
Симптомы
- Шлюз помечает серверную часть как неработоспособную
- Конечная точка работоспособности возвращает значение 401
Solution:
Убедитесь, что конечная точка проверки состояния размещёна перед посредником аутентификации.
// 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
Проблема: ошибки CORS за Front Door
Симптомы
- Сбой запросов preflight OPTIONS
- В консоли браузера отображаются ошибки CORS
Solution:
Добавьте свои источники Front Door и интерфейса в политику 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();
Проблема: предупреждения о "Переадресованном заголовке" в логах
Симптомы
Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware: Unknown proxy
Solution:
Очистите известные сети и прокси-серверы для принятия перенаправленных заголовков от инфраструктуры 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"));
});
Проблема: APIM возвращает 401, но серверная часть возвращает 200
Симптомы
- Токен действителен для бэкенда
- Политика APIM
validate-jwtвызывает ошибку
Solution:
Убедитесь, что аудитория политики APIM соответствует аудитории токенов:
<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>
Проблема: конфликт нескольких схем проверки подлинности
Симптомы
- Использование носителя JWT и других схем аутентификации
- Выбрана неправильная схема
Solution:
Укажите схему проверки подлинности явным образом в контроллере:
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
{
// ...
}
Следуйте лучшим практикам
Примените эти методики для создания безопасного, устойчивого развертывания API за шлюзами.
Глубокая защита
Всегда проверяйте маркеры в серверном API, даже если шлюз проверяет их:
// Gateway validates token (APIM policy)
// Backend ALSO validates token (Microsoft.Identity.Web)
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
Конфигурация шлюза может измениться, а токены могут быть повторно использованы. Защита в глубине крайне важна для безопасности.
2. Используйте управляемые удостоверения для связи между шлюзом и бэкендом.
Если шлюз вызывает бекенд с собственным удостоверением, настройте бекенд, чтобы принимать как пользовательские токены, так и токены управляемого удостоверения.
// 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. Мониторинг метрик шлюза
Отслеживайте эти ключевые метрики, чтобы обеспечить видимость развертывания шлюза:
- Частота ошибок 401/403
- Ошибки проверки токенов
- Сбои тестирования работоспособности
- Перенаправленные заголовки (для отладки)
4. Используйте Application Insights
Добавьте данные телеметрии Application Insights для записи свойств запроса, специфичных для шлюза.
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. Разделение состояния от готовности
Используйте разные точки взаимодействия для работоспособности (работает ли служба?) и готовности (может ли служба обрабатывать трафик?) проверок.
// 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. Документируйте конфигурацию шлюза
Создайте страницу README или вики-страницу, которая содержит документы:
- Какие шлюзы используются
- Ожидания аудитории токенов
- Конфигурация CORS
- Конечные точки пробы работоспособности
- Конфигурация перенаправленных заголовков
- Процедуры аварийного отката
Создание полного примера с помощью Azure API Management
В этом разделе представлен полный, готовый к промышленному использованию пример API ASP.NET Core в Azure API Management с аутентификацией через Microsoft Entra ID.
Backend API (ASP.NET Core)
Следующий Program.cs настраивает перенаправленные заголовки, аутентификацию Microsoft Entra, проверки работоспособности и 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();
Добавьте следующую конфигурацию Microsoft Entra и Application Insights в 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"
}
}
Для следующего контроллера для отладки требуется аутентификация и ведутся журналы перенаправленных заголовков.
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" });
}
}
Конфигурация APIM
Следующая политика входящего трафика проверяет токены JWT, применяет ограничение скорости, перенаправляет заголовки и настраивает 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>