Защита ASP.NET Core Blazor Web App с помощью идентификатора Microsoft Entra
В этой статье описывается, как защитить Blazor Web App пакет Microsoft Platform/Microsoft Identity identity Web для идентификатора Microsoft Entra ID с помощью примера приложения.
Рассматривается следующая спецификация:
- Использует Blazor Web App режим автоматической отрисовки с глобальным взаимодействием (
InteractiveAuto
). - Серверный проект вызывает AddAuthenticationStateSerialization добавление поставщика состояния проверки подлинности на стороне сервера, который используется PersistentComponentState для потока состояния проверки подлинности клиенту. Клиент вызывает AddAuthenticationStateDeserialization десериализацию и использует состояние проверки подлинности, переданное сервером. Состояние проверки подлинности исправлено для времени существования приложения WebAssembly.
- Приложение использует идентификатор Microsoft Entra на основе веб-пакетов МайкрософтIdentity.
- Автоматическое обновление неинтерактивного маркера управляется платформой.
- Приложение использует абстракции на стороне сервера и клиентской службы для отображения созданных данных о погоде:
- При отрисовке
Weather
компонента на сервере для отображения данных о погоде компонент используетсяServerWeatherForecaster
на сервере для непосредственного получения данных о погоде (а не через вызов веб-API). Weather
Когда компонент отрисовывается на клиенте, компонент используетClientWeatherForecaster
реализацию службы, которая использует предварительно настроенную HttpClient (в файле клиентского проектаProgram
) для вызова веб-API для минимального API проекта сервера (/weather-forecast
) для данных о погоде. Минимальная конечная точка API получает данные о погоде изServerWeatherForecaster
класса и возвращает его клиенту для отрисовки компонентом.
- При отрисовке
Пример приложения
Пример приложения состоит из двух проектов:
BlazorWebAppEntra
: серверный проект объекта Blazor Web App, содержащий пример минимальной конечной точки API для данных погоды.BlazorWebAppEntra.Client
: клиентский проект объекта Blazor Web App.
Доступ к примерам приложений с помощью последней папки версии из корневого каталога репозитория с помощью следующей ссылки. Проекты находятся в папке BlazorWebAppEntra
для .NET 9 или более поздней версии.
Просмотреть или скачать образец кода (описание загрузки)
Серверный Blazor Web App проект (BlazorWebAppEntra
)
Проект BlazorWebAppEntra
является серверным проектом Blazor Web App.
Файл BlazorWebAppEntra.http
можно использовать для тестирования запроса данных о погоде. Обратите внимание, что BlazorWebAppEntra
проект должен выполняться для тестирования конечной точки, а конечная точка жестко закодирована в файл. Дополнительные сведения см. в статье "Использование HTTP-файлов в Visual Studio 2022".
Клиентский Blazor Web App проект (BlazorWebAppEntra.Client
)
Проект BlazorWebAppEntra.Client
— это клиентский проект Blazor Web App.
Если пользователю необходимо войти или выйти во время отрисовки на стороне клиента, запускается полная перезагрузка страницы.
Настройка
В этом разделе объясняется, как настроить пример приложения.
AddMicrosoftIdentityWebApp из Microsoft Identity Web (Microsoft.Identity.Web
пакет NuGet, документация по API) настраивается разделом AzureAd
файла проекта appsettings.json
сервера.
При регистрации приложения в Записи или портал Azure используйте конфигурацию веб-платформы с URI https://localhost/signin-oidc
перенаправления (порт не требуется). Убедитесь, что маркеры идентификатора и маркеры доступа в неявном предоставлении и гибридных потоках не выбраны. Обработчик OpenID Connect автоматически запрашивает соответствующие маркеры с помощью кода, возвращенного из конечной точки авторизации.
Настройка приложения
В файле параметров приложения сервера укажитеappsettings.json
конфигурацию раздела приложения AzureAd
. Получите идентификатор приложения (клиента), домен клиента (издателя) и идентификатор каталога (клиента) из регистрации приложения в записи или портал Azure:
"AzureAd": {
"CallbackPath": "/signin-oidc",
"ClientId": "{CLIENT ID}",
"Domain": "{DOMAIN}",
"Instance": "https://login.microsoftonline.com/",
"ResponseType": "code",
"TenantId": "{TENANT ID}"
},
Заполнители в предыдущем примере:
{CLIENT ID}
: идентификатор приложения (клиента).{DOMAIN}
: домен клиента (издателя).{TENANT ID}
: идентификатор каталога (клиента).
Пример:
"AzureAd": {
"CallbackPath": "/signin-oidc",
"ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"Domain": "contoso.onmicrosoft.com",
"Instance": "https://login.microsoftonline.com/",
"ResponseType": "code",
"TenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
},
Путь обратного вызова (CallbackPath
) должен соответствовать URI перенаправления (путь обратного вызова для входа), настроенный при регистрации приложения в Записи или портал Azure. Пути настраиваются в колонке проверки подлинности регистрации приложения. Значение по умолчанию — /signin-oidc
для зарегистрированного URI https://localhost/signin-oidc
перенаправления CallbackPath
(порт не требуется).
Предупреждение
Не сохраняйте секреты приложений, строка подключения, учетные данные, пароли, персональные идентификационные номера (ПИН-коды), частный код C#/.NET или закрытые ключи и токены в клиентском коде, который всегда небезопасн. В средах тестирования и промежуточной и рабочей среды код на стороне Blazor сервера и веб-API должны использовать безопасные потоки проверки подлинности, которые не поддерживают учетные данные в файлах кода проекта или конфигурации. Вне локального тестирования разработки рекомендуется избегать использования переменных среды для хранения конфиденциальных данных, так как переменные среды не являются наиболее безопасным подходом. Для локального тестирования разработки средство Secret Manager рекомендуется для защиты конфиденциальных данных. Дополнительные сведения см. в разделе "Безопасное обслуживание конфиденциальных данных и учетных данных".
Установка секрета клиента
Создайте секрет клиента в регистрации идентификатора записи приложения в записи или портал Azure (управление>сертификатами и секретами>нового секрета клиента). Используйте значение нового секрета в следующем руководстве.
Используйте любой из следующих подходов для предоставления секрета клиента приложению:
- Средство Secret Manager: средство Secret Manager хранит частные данные на локальном компьютере и используется только во время локальной разработки.
- Azure Key Vault. Вы можете хранить секрет клиента в хранилище ключей для использования в любой среде, включая среду разработки при локальной работе. Некоторые разработчики предпочитают использовать хранилища ключей для промежуточных и рабочих развертываний и использовать средство Secret Manager для локальной разработки.
Настоятельно рекомендуется избегать хранения секретов клиента в файлах кода проекта или конфигурации. Используйте безопасные потоки проверки подлинности, например оба подхода в этом разделе.
Средство диспетчера секретов
Средство Secret Manager может хранить секрет клиента приложения сервера под ключом AzureAd:ClientSecret
конфигурации.
Пример приложения не был инициализирован для средства Диспетчера секретов. Используйте командную оболочку, например командную оболочку PowerShell разработчика в Visual Studio, чтобы выполнить следующую команду. Перед выполнением команды измените каталог с cd
помощью команды на каталог проекта сервера. Команда устанавливает идентификатор секретов пользователя (<UserSecretsId>
) в файле проекта приложения сервера, который используется внутри средства для отслеживания секретов для приложения:
dotnet user-secrets init
Выполните следующую команду, чтобы задать секрет клиента. Заполнитель {SECRET}
— это секрет клиента, полученный из регистрации записи приложения:
dotnet user-secrets set "AzureAd:ClientSecret" "{SECRET}"
При использовании Visual Studio можно убедиться, что секрет задан, щелкнув правой кнопкой мыши проект сервера в Обозреватель решений и выбрав "Управление секретами пользователей".
Azure Key Vault
Azure Key Vault обеспечивает безопасный подход для предоставления секрета клиента приложения приложению.
Сведения о создании хранилища ключей и настройке секрета клиента см. в статье "Сведения о секретах Azure Key Vault" (документация Azure), которые перекрестно связывают ресурсы для начала работы с Azure Key Vault. Чтобы реализовать код в этом разделе, запишите URI хранилища ключей и имя секрета из Azure при создании хранилища ключей и секрета. При настройке политики доступа для секрета на панели политик доступа:
- Требуется только разрешение get secret.
- Выберите приложение в качестве участника для секрета.
Внимание
Секрет хранилища ключей создается с датой окончания срока действия. Обязательно отслеживайте срок действия секрета хранилища ключей и создайте новый секрет для приложения до передачи этой даты.
GetKeyVaultSecret
Следующий метод извлекает секрет из хранилища ключей. Добавьте этот метод в серверный проект. Настройте пространство имен (BlazorSample.Helpers
) в соответствии со схемой пространства имен проекта.
Helpers/AzureHelper.cs
:
using Azure;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
namespace BlazorSample.Helpers;
public static class AzureHelper
{
public static string GetKeyVaultSecret(string tenantId, string vaultUri, string secretName)
{
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = tenantId,
SharedTokenCacheTenantId = tenantId
};
var client = new SecretClient(new Uri(vaultUri), new DefaultAzureCredential(options));
var secret = client.GetSecretAsync(secretName).Result;
return secret.Value.Value;
}
}
Где службы зарегистрированы в файле проекта Program
сервера, получите и примените секрет клиента с помощью следующего кода:
var tenantId = builder.Configuration.GetValue<string>("AzureAd:TenantId")!;
var vaultUri = builder.Configuration.GetValue<string>("AzureAd:VaultUri")!;
var secretName = builder.Configuration.GetValue<string>("AzureAd:SecretName")!;
builder.Services.Configure<MicrosoftIdentityOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
options.ClientSecret =
AzureHelper.GetKeyVaultSecret(tenantId, vaultUri, secretName);
});
Если вы хотите управлять средой, в которой работает предыдущий код, например, чтобы избежать локального выполнения кода, так как вы решили использовать средство Secret Manager для локальной разработки, можно упаковать предыдущий код в условный оператор, который проверяет среду:
if (!context.HostingEnvironment.IsDevelopment())
{
...
}
AzureAd
В разделе appsettings.json
добавьте следующие VaultUri
ключи и SecretName
значения конфигурации:
"VaultUri": "{VAULT URI}",
"SecretName": "{SECRET NAME}"
В предыдущем примере:
- Заполнитель
{VAULT URI}
— это универсальный код ресурса (URI) хранилища ключей. Включите косую черту в URI. - Заполнитель
{SECRET NAME}
— это имя секрета.
Пример:
"VaultUri": "https://contoso.vault.azure.net/",
"SecretName": "BlazorWebAppEntra"
Конфигурация используется для упрощения предоставления выделенных хранилищ ключей и имен секретов на основе файлов конфигурации среды приложения. Например, можно указать различные значения appsettings.Development.json
конфигурации для разработки, appsettings.Staging.json
при промежуточном и appsettings.Production.json
рабочем развертывании. Дополнительные сведения см. в статье Конфигурация ASP.NET Core Blazor.
Перенаправление home на страницу выхода
Когда пользователь перемещается по приложению, компонент (Layout/LogInOrOut.razor
) задает скрытое поле для возвращаемого URL-адреса (ReturnUrl
) значение текущего URL-адреса (currentURL
).LogInOrOut
Когда пользователь выходит из приложения, identity поставщик возвращает их на страницу, из которой они вышли.
Если пользователь выходит из безопасной страницы, он возвращается обратно на ту же безопасную страницу после выхода только для отправки через процесс проверки подлинности. Это поведение хорошо, если пользователям нужно часто переключать учетные записи. Однако альтернативная спецификация приложения может вызвать возвращение пользователя на страницу приложения home или на другую страницу после выхода. В следующем примере показано, как задать страницу приложения home в качестве URL-адреса возврата для операций выхода.
Важные изменения LogInOrOut
компонента показаны в следующем примере. Нет необходимости указать скрытое поле для ReturnUrl
набора home /
страницы, так как это путь по умолчанию. IDisposable больше не реализуется. Больше NavigationManager не внедряется. Весь @code
блок удаляется.
Layout/LogInOrOut.razor
:
@using Microsoft.AspNetCore.Authorization
<div class="nav-item px-3">
<AuthorizeView>
<Authorized>
<form action="authentication/logout" method="post">
<AntiforgeryToken />
<button type="submit" class="nav-link">
<span class="bi bi-arrow-bar-left-nav-menu" aria-hidden="true">
</span> Logout @context.User.Identity?.Name
</button>
</form>
</Authorized>
<NotAuthorized>
<a class="nav-link" href="authentication/login">
<span class="bi bi-person-badge-nav-menu" aria-hidden="true"></span>
Login
</a>
</NotAuthorized>
</AuthorizeView>
</div>
Устранение неполадок
Ведение журнала
Серверное приложение — это стандартное приложение ASP.NET Core. Ознакомьтесь с руководством по ведению журнала ASP.NET Core, чтобы включить более низкий уровень ведения журнала в серверном приложении.
Чтобы включить ведение журнала отладки или трассировки для Blazor WebAssembly проверки подлинности, см. раздел Blazor ведения журнала проверки подлинности на стороне клиента ASP.NET Core с селектором версий статьи, установленным для ASP.NET Core 7.0 или более поздней версии.
Распространенные ошибки
Неправильная настройка приложения или поставщика Identity (IP)
Наиболее частые ошибки вызваны неправильной настройкой. Ниже приводятся несколько примеров.
- В зависимости от требований сценария, отсутствующие или неправильные элементы, такие как центр сертификации, экземпляр, идентификатор арендатора, домен арендатора, идентификатор клиента или URI перенаправления, не позволяют приложению осуществлять проверку подлинности клиентов.
- Неверные области запросов не позволяют клиентам получать доступ к конечным точкам веб-API сервера.
- Неправильные или отсутствующие разрешения API сервера не позволяют клиентам получить доступ к конечным точкам веб-API сервера.
- Запуск приложения на порте, отличном от настроенного в URI перенаправления регистрации приложения IP-адреса. Обратите внимание, что порт не требуется для идентификатора Microsoft Entra и приложения, работающего на
localhost
адресе тестирования разработки, но конфигурация порта приложения и порт, на котором выполняется приложение, должно соответствовать не-адресамlocalhost
.
Покрытие конфигурации в этой статье показывает примеры правильной конфигурации. Тщательно проверьте конфигурацию, ищете неправильное настройку приложения и IP-адреса.
Если конфигурация верна, выполните приведенные ниже действия.
Проанализируйте журналы приложений.
Изучите трафик между клиентским приложением и серверным приложением или приложением поставщика удостоверений с помощью инструментов разработчика браузера. Зачастую точное сообщение об ошибке или сообщение с указанием на то, что вызывает проблему, возвращается клиенту с помощью серверного приложения или приложения поставщика удостоверений после выполнения запроса. Руководство по инструментам разработчика можно найти в следующих статьях:
- Google Chrome (документация по Google)
- Microsoft Edge
- Mozilla Firefox (документация по Mozilla)
Команда разработчиков документации реагирует на отзывы о документах и ошибки в статьях (откройте запрос в разделе отзывов на этой странице), но не может предоставить поддержку продукта. Помощь в устранении неполадок в приложении предоставляют несколько общественных форумов поддержки. Мы рекомендуем следующее:
Указанные выше форумы не принадлежат корпорации Майкрософт и не управляются ею.
Чтобы сообщить об ошибках с воспроизведением платформы, которые не связаны с безопасностью и конфиденциальностью, откройте запрос с единицей продукта ASP.NET Core. Не открывайте запрос с единицей продукта, пока вы тщательно не изучите причину проблемы и не попытаетесь решить ее самостоятельно или с помощью сообщества на общедоступном форуме поддержки. Единица продукта не способна устранять неполадки отдельных приложений, которые не работают из-за неправильной конфигурации или вариантов использования с участием сторонних служб. Если отчет является конфиденциальным или конфиденциальным в природе или описывает потенциальный недостаток безопасности в продукте, который может использовать злоумышленники, см. статью "Отчеты о проблемах безопасности и ошибках" (
dotnet/aspnetcore
репозиторий GitHub).Несанкционированный клиент для ME-ID
info: сбой авторизации Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]. Эти требования не выполнены: DenyAnonymousAuthorizationRequirement: требуется прошедший проверку подлинности пользователь.
Ошибка обратного вызова входа из ME-ID:
- Ошибка:
unauthorized_client
- Описание:
AADB2C90058: The provided application is not configured to allow public clients.
Чтобы устранить эту ошибку, сделайте следующее:
- На портале Azure перейдите к манифесту приложения.
- Задайте для атрибута
allowPublicClient
значениеnull
илиtrue
.
- Ошибка:
Файлы cookie и данные сайта
Файлы cookie и данные сайта могут сохраняться в разных обновлениях приложений и повлиять на тестирование и устранение неполадок. При внесении изменений в код приложения, изменений в учетную запись пользователя у поставщика или изменений конфигурации приложения поставщика очистите следующее:
- файлы cookie входа пользователей;
- файлы cookie приложения;
- кэшированные и сохраненные данные сайта.
Один из подходов, позволяющих предотвратить влияние устаревших файлов cookie и данных сайта на тестирование и устранение неполадок заключается в следующем:
- Настройка браузера
- Для тестирования используйте браузер, в котором можно настроить удаление всех файлов cookie и данных сайта при каждом закрытии браузера.
- Убедитесь, что при любых изменениях в приложении, в данных тестового пользователя или в конфигурации поставщика закрытие браузера выполняется вручную или интегрированной средой разработки.
- Используйте пользовательскую команду, чтобы открыть браузер в режиме InPrivate или Incognito в Visual Studio:
- Откройте диалоговое окно Просмотр с помощью, которое можно выбрать с помощью кнопки Запустить в Visual Studio.
- Нажмите кнопку Добавить.
- Укажите путь к браузеру в поле Программа. Следующие пути к исполняемым файлам являются типичными расположениями установки для Windows 10. Если браузер установлен в другом расположении или вы используете операционную систему, отличную от Windows 10, укажите путь к исполняемому файлу браузера.
- Microsoft Edge:
C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
- Google Chrome:
C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
- Mozilla Firefox:
C:\Program Files\Mozilla Firefox\firefox.exe
- Microsoft Edge:
- В поле "Аргументы" укажите параметр командной строки, который браузер использует для открытия в режиме InPrivate или Incognito. Для некоторых браузеров требуется URL-адрес приложения.
- Microsoft Edge: используйте
-inprivate
. - Google Chrome: используйте
--incognito --new-window {URL}
, где{URL}
заполнитель является URL-адресом для открытия (например,https://localhost:5001
). - Mozilla Firefox: используйте
-private -url {URL}
, где{URL}
заполнитель является URL-адресом для открытия (например,https://localhost:5001
).
- Microsoft Edge: используйте
- Введите имя в поле Понятное имя. Например,
Firefox Auth Testing
. - Выберите кнопку ОК.
- Чтобы не выбирать профиль браузера для каждой операции тестирования с помощью приложения, задайте профиль по умолчанию с помощью кнопки По умолчанию.
- Убедитесь, что при любых изменениях в приложении, в данных тестового пользователя или в конфигурации поставщика закрытие браузера выполняется интегрированной средой разработки.
Обновление приложений
Приложения-функции могут перестать работать сразу после обновления пакета SDK для .NET Core на компьютере разработки или обновления версии пакетов в самом приложении. В некоторых случаях в результате важного обновления несогласованные версии пакетов могут привести к нарушению работы приложения. Большинство этих проблем можно исправить следующим образом:
- Очистите кэши пакетов NuGet локальных систем, выполнив команду
dotnet nuget locals all --clear
из командной оболочки. - Удалите папки
bin
иobj
проекта. - Восстановите и перестройте проект.
- Удалите все файлы из папки развертывания на сервере, прежде чем повторно развернуть приложение.
Примечание.
Использование версий пакета, несовместимых с требуемой платформой приложения, не поддерживается. Дополнительные сведения о пакете см. на странице коллекций NuGet или обозревателя пакетов FuGet.
Запуск серверного приложения
При тестировании и устранении Blazor Web Appнеполадок убедитесь, что приложение запущено из серверного проекта.
Проверка пользователя
Следующий UserClaims
компонент можно использовать непосредственно в приложениях или служить основой для дальнейшей настройки.
UserClaims.razor
:
@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
<PageTitle>User Claims</PageTitle>
<h1>User Claims</h1>
@if (claims.Any())
{
<ul>
@foreach (var claim in claims)
{
<li><b>@claim.Type:</b> @claim.Value</li>
}
</ul>
}
@code {
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; }
protected override async Task OnInitializedAsync()
{
if (AuthState == null)
{
return;
}
var authState = await AuthState;
claims = authState.User.Claims;
}
}
Дополнительные ресурсы
- Документация по платформе Майкрософт identity
AzureAD/microsoft-identity-web
Репозиторий GitHub: полезное руководство по реализации Microsoft Web для идентификатора Microsoft Identity Entra и Azure Active Directory B2C для приложений ASP.NET Core, включая ссылки на примеры приложений и соответствующую документацию По Azure. Blazor Web AppВ настоящее время в документации Azure не рассматриваются явным образом, но настройка и настройка Blazor Web App для ME-ID и размещения Azure совпадают с тем, что и для любого веб-приложения ASP.NET Core.AuthenticationStateProvider
служба- Управление состоянием проверки подлинности в Blazor Web Apps
- Абстракции служб в Blazor Web Apps
ASP.NET Core