Защита ASP.NET Core Blazor WebAssembly с помощью ASP.NET Core Identity
Blazor WebAssembly Автономные приложения можно защитить с помощью ASP.NET CoreIdentity, следуя инструкциям в этой статье.
Конечные точки для регистрации, входа в систему и выхода из системы
Вместо использования пользовательского интерфейса по умолчанию, предоставленного ASP.NET Core Identity для SPA и Blazor приложений, основанных на Razor страницах, вызовите MapIdentityApi внутренний API для добавления конечных точек API JSON для регистрации и входа пользователей с ASP.NET Core Identity. Identity Конечные точки API также поддерживают расширенные функции, такие как двухфакторная проверка подлинности и проверка электронной почты.
На клиенте вызовите /register
конечную точку, чтобы зарегистрировать пользователя с помощью адреса электронной почты и пароля:
var result = await _httpClient.PostAsJsonAsync(
"register", new
{
email,
password
});
В клиенте войдите в систему пользователя с проверкой подлинности с cookie помощью конечной точки со useCookies
строкой запроса, заданной /login
в true
следующих значениях:
var result = await _httpClient.PostAsJsonAsync(
"login?useCookies=true", new
{
email,
password
});
API серверного сервера устанавливает cookie проверку подлинности с вызовом AddIdentityCookies в построителе проверки подлинности:
builder.Services
.AddAuthentication(IdentityConstants.ApplicationScheme)
.AddIdentityCookies();
Проверка подлинности на базе токенов
Для собственных и мобильных сценариев, когда некоторые клиенты не поддерживают файлы cookie, API входа предоставляет параметр для запроса маркеров.
Предупреждение
Мы рекомендуем использовать файлы cookie для приложений на основе браузера вместо маркеров, так как браузер обрабатывает файлы cookie, не предоставляя их JavaScript. Если вы решили использовать безопасность на основе маркеров в веб-приложениях, вы несете ответственность за обеспечение безопасности маркеров.
Выдается пользовательский маркер (который является владельцем платформы ASP.NET Core Identity ), который можно использовать для проверки подлинности последующих запросов. Маркер должен передаваться в заголовке Authorization
в качестве маркера носителя. Также предоставляется маркер обновления. Этот маркер позволяет приложению запрашивать новый маркер, когда срок действия старого маркера истекает без повторного входа пользователя.
Маркеры не являются стандартными веб-маркерами JSON (JWTs). Использование пользовательских маркеров намеренно, так как встроенный Identity API предназначен в первую очередь для простых сценариев. Параметр токена не предназначен для полнофункционального identity поставщика услуг или сервера маркеров, а вместо этого альтернативой cookie для клиентов, которые не могут использовать файлы cookie.
В следующем руководстве начинается процесс реализации проверки подлинности на основе маркеров с помощью API входа. Для завершения реализации требуется пользовательский код. Дополнительные сведения см. в статье "Защита Identity серверной части веб-API для spAs".
Вместо API серверного сервера, устанавливающего cookie проверку подлинности с вызовом AddIdentityCookies в построителе проверки подлинности, API сервера настраивает проверку подлинности маркера носителя с AddBearerToken помощью метода расширения. Укажите схему маркеров проверки подлинности носителя с IdentityConstants.BearerSchemeпомощью .
В Backend/Program.cs
этом случае измените службы проверки подлинности и конфигурацию следующим образом:
builder.Services
.AddAuthentication()
.AddBearerToken(IdentityConstants.BearerScheme);
Удалите BlazorWasmAuth/Identity/CookieAuthenticationStateProvider.cs
параметр строки запроса в методе LoginAsync
CookieAuthenticationStateProvider
:useCookies
- login?useCookies=true
+ login
На этом этапе необходимо предоставить пользовательский код для анализа AccessTokenResponse клиента и управления маркерами доступа и обновления. Дополнительные сведения см. в статье "Защита Identity серверной части веб-API для spAs".
Дополнительные Identity сценарии
Дополнительные Identity сценарии, предоставляемые API, см. в статье "Использование Identity для защиты серверной части веб-API для spAs:
- Защита выбранных конечных точек
- Проверка подлинности на базе токенов
- Двухфакторная проверка подлинности (2FA)
- Коды восстановления
- Управление сведениями пользователей
Использование безопасных потоков проверки подлинности для поддержания конфиденциальных данных и учетных данных
Предупреждение
Не сохраняйте секреты приложений, строка подключения, учетные данные, пароли, персональные идентификационные номера (ПИН-коды), частный код C#/.NET или закрытые ключи и токены в клиентском коде, который всегда небезопасн. В средах тестирования и промежуточной и рабочей среды код на стороне Blazor сервера и веб-API должны использовать безопасные потоки проверки подлинности, которые не поддерживают учетные данные в файлах кода проекта или конфигурации. Вне локального тестирования разработки рекомендуется избегать использования переменных среды для хранения конфиденциальных данных, так как переменные среды не являются наиболее безопасным подходом. Для локального тестирования разработки средство Secret Manager рекомендуется для защиты конфиденциальных данных. Дополнительные сведения см. в разделе "Безопасное обслуживание конфиденциальных данных и учетных данных".
Примеры приложений
В этой статье примеры приложений служат ссылкой для автономных Blazor WebAssembly приложений, которые обращаются к ASP.NET Core Identity через внутренний веб-API. Демонстрация включает в себя два приложения:
Backend
: серверное веб-ПРИЛОЖЕНИЕ API, которое поддерживает пользовательское identity хранилище для ASP.NET Core Identity.BlazorWasmAuth
: автономное Blazor WebAssembly интерфейсное приложение с проверкой подлинности пользователя.
Перейдите к примеру приложений через последнюю папку версии из корневого каталога репозитория, используя следующую ссылку. Примеры предоставляются для .NET 8 или более поздней версии. Сведения о запуске примеров приложений см. README
в BlazorWebAssemblyStandaloneWithIdentity
папке в папке.
Просмотреть или скачать образец кода (описание загрузки)
Пакеты и код внутреннего веб-API веб-API
Серверное веб-ПРИЛОЖЕНИЕ API поддерживает пользовательское identity хранилище для ASP.NET Core Identity.
Packages
Приложение использует следующие пакеты NuGet:
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.EntityFrameworkCore.InMemory
NSwag.AspNetCore
Если приложение предназначено для использования другого EF Core поставщика базы данных, отличного от поставщика в памяти, не создавайте ссылку на пакет в приложении Microsoft.EntityFrameworkCore.InMemory
.
В файле проекта приложения (.csproj
) настраивается инвариантная глобализация .
Пример кода приложения
Параметры приложения настраивают внутренние и внешние URL-адреса:
Backend
приложение (BackendUrl
):https://localhost:7211
BlazorWasmAuth
приложение (FrontendUrl
):https://localhost:7171
Файл Backend.http
можно использовать для тестирования запроса данных о погоде. Обратите внимание, что BlazorWasmAuth
приложение должно выполняться для тестирования конечной точки, а конечная точка жестко закодирована в файл. Дополнительные сведения см. в статье "Использование HTTP-файлов в Visual Studio 2022".
Следующая настройка и конфигурация находятся в файле приложенияProgram
.
Пользователь identity с cookie проверкой подлинности добавляется путем вызова AddAuthentication и AddIdentityCookies. Службы проверки авторизации добавляются вызовом AddAuthorizationBuilder.
Рекомендуется только для демонстраций, приложение использует EF Core поставщика базы данных в памяти для регистрации контекста базы данных (AddDbContext). Поставщик базы данных в памяти упрощает перезапуск приложения и проверяет потоки пользователей регистрации и входа. Каждое выполнение начинается с новой базы данных, но приложение включает тестовый демонстрационный код для пользователей, который описан далее в этой статье. Если база данных изменена на SQLite, пользователи сохраняются между сеансами, но база данных должна быть создана с помощью миграций, как показано вEF Core руководстве по началу работы†. Для рабочего кода можно использовать другие реляционные поставщики, такие как SQL Server.
Примечание.
† Учебник EF Core по началу работы использует команды PowerShell для выполнения миграций баз данных при использовании Visual Studio. Альтернативный подход в Visual Studio — использовать пользовательский интерфейс подключенных служб:
В Обозреватель решений дважды щелкните подключенные службы. В зависимостях>служб SQL Server Express LocalDB выберите многоточие (...
), а затем добавьте миграцию, чтобы создать миграцию или обновить базу данных для обновления базы данных.
Настройте Identity для использования EF Core базы данных и предоставления Identity конечных точек через вызовы AddIdentityCore, AddEntityFrameworkStoresа также AddApiEndpoints.
Политика общего доступа к ресурсам (CORS) между источниками устанавливается для разрешения запросов от интерфейсных и внутренних приложений. Резервные URL-адреса настраиваются для политики CORS, если параметры приложения не предоставляют их:
Backend
приложение (BackendUrl
):https://localhost:5001
BlazorWasmAuth
приложение (FrontendUrl
):https://localhost:5002
Службы и конечные точки для Swagger/OpenAPI включены в документацию по веб-API и тестирование разработки. Дополнительные сведения о NSwag см. в статье "Начало работы с NSwag" и ASP.NET Core.
Утверждения роли пользователя отправляются из минимального API на конечной точке/roles
.
Маршруты сопоставляются для Identity конечных точек путем вызова MapIdentityApi<AppUser>()
.
Конечная точка выхода (/Logout
) настраивается в конвейере ПО промежуточного слоя для выхода пользователей.
Чтобы защитить конечную точку, добавьте RequireAuthorization метод расширения в определение маршрута. Для контроллера добавьте атрибут в [Authorize]
контроллер или действие.
Дополнительные сведения о базовых шаблонах инициализации и конфигурации экземпляра DbContext см. в EF Core документации по времени существования, конфигурации и инициализации DbContext.
Пакеты и код автономных Blazor WebAssembly приложений frontend
Автономное Blazor WebAssembly интерфейсное приложение демонстрирует проверку подлинности пользователей и авторизацию для доступа к частной веб-странице.
Packages
Приложение использует следующие пакеты NuGet:
Microsoft.AspNetCore.Components.WebAssembly.Authentication
Microsoft.Extensions.Http
Microsoft.AspNetCore.Components.WebAssembly
Microsoft.AspNetCore.Components.WebAssembly.DevServer
Пример кода приложения
Папка Models
содержит модели приложения:
FormResult
(Identity/Models/FormResult.cs
): ответ на вход и регистрацию.UserInfo
(Identity/Models/UserInfo.cs
): сведения о пользователе из identity конечной точки для установления утверждений.
Интерфейс IAccountManagement
(Identity/CookieHandler.cs
) предоставляет службы управления учетными записями.
Класс () обрабатывает состояние проверки подлинности на cookieоснове и предоставляет реализации службы управления учетными записями, описанные в интерфейсеIAccountManagement
.Identity/CookieAuthenticationStateProvider.cs
CookieAuthenticationStateProvider
Метод LoginAsync
явно включает cookie проверку подлинности через useCookies
строковое значение true
запроса. Класс также управляет созданием утверждений ролей для прошедших проверку подлинности пользователей.
Класс CookieHandler
(Identity/CookieHandler.cs
) гарантирует, что cookie учетные данные отправляются с каждым запросом на внутренний веб-API, который обрабатывает Identity и поддерживает Identity хранилище данных.
Предоставляет wwwroot/appsettings.file
конечные точки внутренних и интерфейсных URL-адресов.
Компонент App
предоставляет состояние проверки подлинности в виде каскадного параметра. Дополнительные сведения см. в разделе ASP.NET Проверка подлинности и авторизация CoreBlazor.
Компонент MainLayout
и NavMenu
компонент используют AuthorizeView
компонент для выборочного отображения содержимого на основе состояния проверки подлинности пользователя.
Следующие компоненты обрабатывают распространенные задачи проверки подлинности пользователей IAccountManagement
, используя службы:
Register
компонент (Components/Identity/Register.razor
)Login
компонент (Components/Identity/Login.razor
)Logout
компонент (Components/Identity/Logout.razor
)
Компонент PrivatePage
(Components/Pages/PrivatePage.razor
) требует проверки подлинности и отображает утверждения пользователя.
Службы и конфигурация предоставляются в Program
файле (Program.cs
):
- Обработчик cookie регистрируется в качестве службы с областью действия.
- Службы авторизации регистрируются.
- Настраиваемый поставщик состояний проверки подлинности регистрируется в качестве службы с областью действия.
- Регистрируется интерфейс
IAccountManagement
управления учетными записями. - URL-адрес базового узла настроен для зарегистрированного экземпляра клиента HTTP.
- Базовый внутренний URL-адрес настраивается для зарегистрированного экземпляра клиента HTTP, который используется для проверки подлинности с серверным веб-API. HTTP-клиент использует cookie обработчик, чтобы убедиться, что cookie учетные данные отправляются с каждым запросом.
Вызов при AuthenticationStateProvider.NotifyAuthenticationStateChanged изменении состояния проверки подлинности пользователя. Пример см LoginAsync
. в разделе и LogoutAsync
методы CookieAuthenticationStateProvider
класса (Identity/CookieAuthenticationStateProvider.cs
).
Предупреждение
Компонент AuthorizeView избирательно демонстрирует содержимое пользовательского интерфейса в зависимости от того, авторизован ли пользователь. Все содержимое в приложении, размещенном в компоненте Blazor WebAssembly AuthorizeView , доступно без проверки подлинности, поэтому конфиденциальное содержимое должно быть получено из веб-API на серверном сервере после успешной проверки подлинности. Дополнительные сведения см. на следующих ресурсах:
Тестовая демонстрация заполнения пользователей
Класс SeedData
(SeedData.cs
) демонстрирует создание тестовых пользователей для разработки. Тестовый пользователь с именем Leela войдите в приложение с помощью адреса leela@contoso.com
электронной почты. Для пароля пользователя задано Passw0rd!
значение . Leela предоставляется Administrator
и Manager
роли для авторизации, что позволяет пользователю получить доступ к странице руководителя, /private-manager-page
но не на странице /private-editor-page
редактора.
Предупреждение
Никогда не разрешать запуск тестового пользовательского кода в рабочей среде. SeedData.InitializeAsync
вызывается только в Development
среде в Program
файле:
if (builder.Environment.IsDevelopment())
{
await using var scope = app.Services.CreateAsyncScope();
await SeedData.InitializeAsync(scope.ServiceProvider);
}
Роли
Из-за проблемы с проектированием платформы (dotnet/aspnetcore
#50037) утверждения ролей не отправляются из manage/info
конечной точки для создания утверждений пользователей для пользователей BlazorWasmAuth
приложения. Утверждения ролей управляются независимо через отдельный запрос в GetAuthenticationStateAsync
методеCookieAuthenticationStateProvider
класса (Identity/CookieAuthenticationStateProvider.cs
) после проверки подлинности пользователя в Backend
проекте.
В запросе CookieAuthenticationStateProvider
ролей выполняется /roles
запрос на конечную точку Backend
проекта API сервера. Ответ считывается в строку путем вызова ReadAsStringAsync(). JsonSerializer.Deserialize десериализирует строку в пользовательский RoleClaim
массив. Наконец, утверждения добавляются в коллекцию утверждений пользователя.
В файле API Program
сервера минимальный Backend
API управляет конечной /roles
точкой. RoleClaimType Утверждения выбираются в анонимный тип и сериализуются для возврата в BlazorWasmAuth
проект.TypedResults.Json
Конечная точка ролей требует авторизации путем вызова RequireAuthorization. Если вы решили не использовать минимальные API в пользу контроллеров для конечных точек API безопасного сервера, обязательно установите [Authorize]
атрибут на контроллерах или действиях.
Размещение между доменами (конфигурация одного сайта)
Примеры приложений настроены для размещения обоих приложений в одном домене. Если приложение размещается Backend
в другом домене, отличном BlazorWasmAuth
от приложения, раскомментируйте код, который настраивает cookie (ConfigureApplicationCookie) в Backend
файле приложения Program
. Значения по умолчанию:
- Режим одного сайта: SameSiteMode.Lax
- Безопасная политика: CookieSecurePolicy.SameAsRequest
Измените значения следующими значениями:
- Режим одного сайта: SameSiteMode.None
- Безопасная политика: CookieSecurePolicy.Always
- options.Cookie.SameSite = SameSiteMode.Lax;
- options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
+ options.Cookie.SameSite = SameSiteMode.None;
+ options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
Дополнительные сведения о параметрах одного сайта cookie см. в следующих ресурсах:
- Set-Cookie:
SameSite=<samesite-value>
(документация по MDN) - Файлы cookie: механизм управления состояниями HTTP (RFC Черновик 6265, раздел 4.1)
Поддержка антифоргерии
Только конечная точка выхода (/logout
) в Backend
приложении требует внимания для устранения угрозы кросс-сайта Forgery (CSRF).
Конечная точка выхода проверяет пустой текст, чтобы предотвратить атаки CSRF. Если требуется текст, запрос должен выполняться из JavaScript, который является единственным способом доступа к проверке подлинности cookie. Конечная точка выхода не может быть доступ к ней с помощью POST на основе форм. Это предотвращает выход злоумышленника из системы.
Кроме того, конечная точка защищена авторизацией (RequireAuthorization), чтобы предотвратить анонимный доступ.
Клиентское BlazorWasmAuth
приложение просто необходимо передать пустой объект {}
в тексте запроса.
За пределами конечной точки выхода защита от угроз требуется только при отправке данных формы на сервер, закодированный как application/x-www-form-urlencoded
, multipart/form-data
или text/plain
. Blazor Управляет устранением рисков CSRF для форм в большинстве случаев. Дополнительные сведения см. в статье ASP.NET Проверка подлинности и авторизация Core Blazor и обзор ASP.NET основных Blazor форм.
Запросы к другим конечным точкам API сервера (веб-API) с содержимым с application/json
кодировкой CORS не требуют защиты CSRF. Поэтому для конечной точки обработки данных (/data-processing
) приложения не требуется Backend
защита CSRF. Конечная точка ролей/roles
не нуждается в защите CSRF, так как это конечная точка GET, которая не изменяет состояние.
Устранение неполадок
Ведение журнала
Сведения о включении ведения журнала отладки или трассировки для Blazor WebAssembly проверки подлинности см. в разделе ASP.NET ведения журнала CoreBlazor.
Распространенные ошибки
Проверьте конфигурацию каждого проекта. Убедитесь, что URL-адреса верны:
Backend
проектappsettings.json
BackendUrl
FrontendUrl
Backend.http
:Backend_HostAddress
BlazorWasmAuth
проект:wwwroot/appsettings.json
BackendUrl
FrontendUrl
Если конфигурация верна, выполните приведенные ниже действия.
Проанализируйте журналы приложений.
Изучите сетевой трафик между приложением
BlazorWasmAuth
иBackend
приложением с помощью средств разработчика браузера. Часто точное сообщение об ошибке или сообщение с подсказкой о том, что вызывает проблему, возвращается клиенту серверным приложением после выполнения запроса. Руководство по инструментам разработчика можно найти в следующих статьях:Google Chrome (документация по Google)
Mozilla Firefox (документация по Mozilla)
Команда документации отвечает на отзывы о документах и ошибки в статьях. Откройте проблему, используя ссылку "Открыть документацию" в нижней части статьи. Команда не может предоставлять поддержку продукта. Помощь в устранении неполадок в приложении предоставляют несколько общественных форумов поддержки. Мы рекомендуем следующее:
Указанные выше форумы не принадлежат корпорации Майкрософт и не управляются ею.
Чтобы сообщить об ошибках с воспроизведением платформы, которые не связаны с безопасностью и конфиденциальностью, откройте запрос с единицей продукта ASP.NET Core. Не открывайте запрос с единицей продукта, пока вы тщательно не изучите причину проблемы и не попытаетесь решить ее самостоятельно или с помощью сообщества на общедоступном форуме поддержки. Единица продукта не способна устранять неполадки отдельных приложений, которые не работают из-за неправильной конфигурации или вариантов использования с участием сторонних служб. Если отчет является конфиденциальным или конфиденциальным в природе или описывает потенциальный недостаток безопасности в продукте, который может использовать злоумышленники, см. статью "Отчеты о проблемах безопасности и ошибках" (dotnet/aspnetcore
репозиторий GitHub).
Файлы 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.
Проверка утверждений пользователя
Чтобы устранить неполадки с утверждениями пользователей, следующий UserClaims
компонент можно использовать непосредственно в приложениях или служить основой для дальнейшей настройки.
UserClaims.razor
:
@page "/user-claims"
@using System.Security.Claims
@attribute [Authorize]
<PageTitle>User Claims</PageTitle>
<h1>User Claims</h1>
**Name**: @AuthenticatedUser?.Identity?.Name
<h2>Claims</h2>
@foreach (var claim in AuthenticatedUser?.Claims ?? Array.Empty<Claim>())
{
<p class="claim">@(claim.Type): @claim.Value</p>
}
@code {
[CascadingParameter]
private Task<AuthenticationState>? AuthenticationState { get; set; }
public ClaimsPrincipal? AuthenticatedUser { get; set; }
protected override async Task OnInitializedAsync()
{
if (AuthenticationState is not null)
{
var state = await AuthenticationState;
AuthenticatedUser = state.User;
}
}
}
Дополнительные ресурсы
ASP.NET Core