Доступен накопительный пакет исправлений (сборка 4.3.2195.0) для Microsoft Identity Manager 2016
Для Microsoft Identity Manager (MIM) 2016 доступен накопительный пакет исправлений (сборки 4.3.2195.0). Данный пакет устраняет некоторые проблемы и добавляет некоторые функции, описанные в разделе «Дополнительные сведения».
Сведения об обновлении
Поддерживается обновление доступно в службу технической поддержки Майкрософт. Рекомендуется применять это обновление всех клиентов для своих производственных систем.
Служба технической поддержки Майкрософт
Если это обновление доступно для загрузки в службу технической поддержки Microsoft, имеется раздел «Исправление доступно для загрузки» в верхней части этой статьи базы знаний. Если этот раздел не отображается, обратитесь в службу поддержки для получения исправления. Кроме того можно получить обновления из центра обновления Майкрософт или из каталога Центра обновления Майкрософт.
Примечание. Если наблюдаются другие проблемы или необходимо устранить неполадки, вам может понадобиться создать отдельный запрос на обслуживание. Стандартная оплата за поддержку будет взиматься только за дополнительные вопросы и проблемы, которые не соответствуют требованиям конкретного исправления. Чтобы просмотреть полный список телефонов поддержки и обслуживания клиентов корпорации Майкрософт или создать отдельный запрос на обслуживание, посетите следующий веб-сайт корпорации Майкрософт:
http://support.microsoft.com/contactus/?ws=supportПримечание. В форме «Пакет исправлений доступен для скачивания» отображаются языки, для которых доступно исправление. Если нужный язык не отображается, значит исправление для данного языка отсутствует.
Известные проблемы этого обновления
После установки данного обновления для расширения правил и агентами управления (MAs), основанные на расширяемая мА (ECMA1 или ECMA 2.0) может работать и могут привести к выполнения состояние «остановлен расширение dll загрузка.» Эта проблема возникает при выполнении такого правила расширения или пользовательские MAs после изменения файла конфигурации (.config) для одного из следующих процессов:
- MIIServer.exe
- Mmsscrpt.exe
- Dllhost.exe
Например редактировать файл MIIServer.exe.config Чтобы изменить размер пакета по умолчанию для обработки операций синхронизации FIM службы мА.
В этом случае установщик механизм синхронизации для обновления намеренно не заменяет файл конфигурации, чтобы избежать удаления предыдущих изменений. Поскольку файл конфигурации не будет заменен, операции, необходимые для обновления не будет присутствовать в файлах и обработчик синхронизации не будет загружать любого правила расширения DLL Если ядро запускает полный импорт или запустить профиль синхронизации дельта.
Чтобы устранить эту проблему, выполните следующие действия:
- Создайте резервную копию файла MIIServer.exe.config.
- Откройте файл MIIServer.exe.config в текстовом редакторе или в Microsoft Visual Studio.
- Найдите раздел < время >выполнения в файле MIIServer.exe.config и затем замените содержимое раздела < dependentAssembly >следующим кодом:
Предварительные условия
Чтобы применить это обновление, необходимо иметь Microsoft Identity Manager 2016 сборки 4.3.1935.0 или более поздней версии построения установлен.
Для развертываний пакет BHOLD пакет BHOLD FIM интеграции модуля или разъем управления доступом необходимо иметь накопительный пакет (4.3.2195.0) установлен на серверах MIM до обновления любой пакет BHOLD модулей.
Необходимость перезагрузки
Необходимо перезагрузить компьютер после установки пакета надстройки и расширения (Fimaddinsextensions_xnn_kb3134725.msp). Кроме того может потребоваться перезагрузка компонентов сервера.
Сведения о замене
Это обновление заменяет обновление 3092179 (сборки 4.3.2064.0) 2016 Microsoft Identity Manager.
Сведения о файлах
Общая версия данного обновления содержит атрибуты файла (или более поздние атрибуты файлов), приведенные в следующей таблице. Дата и время для этих файлов указаны в формате общего скоординированного времени (UTC). При просмотре сведений о файле, он преобразуется в локальное время. Чтобы узнать разницу между временем по Гринвичу и местным временем, откройте вкладку Часовой пояс элемента Дата и время в панели управления.
Размер файла (в байтах)
Классическое приложение, которое вызывает веб-API: Получение маркера в интерактивном режиме
В следующем примере показан минимальный код для интерактивного получения маркера для чтения профиля пользователя с Microsoft Graph.
Код в MSAL.NET
string[] scopes = new string[] ; var app = PublicClientApplicationBuilder.Create(clientId).Build(); var accounts = await app.GetAccountsAsync(); AuthenticationResult result; try < result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()) .ExecuteAsync(); >catch(MsalUiRequiredException)
Обязательные параметры
AcquireTokenInteractive имеет только один обязательный параметр, scopes . Он содержит перечисление строк, определяющих область, для которых требуется маркер. Если маркер предназначен для Microsoft Graph, вы можете найти необходимые область в справочнике по API каждого API Microsoft Graph в разделе «Разрешения». Например, для перечисления контактов пользователя необходимо использовать оба User.Read и Contacts.Read как область. См. сведения о разрешениях Microsoft Graph.
В классических и мобильных приложениях важно указать родительский элемент с помощью .WithParentActivityOrWindow . Во многих случаях это требование, и MSAL выдает исключения.
Сведения о классических приложениях см. в разделе «Родительские дескрипторы окон».
Для мобильных приложений укажите Activity (Android) или UIViewController (iOS).
Необязательные параметры в MSAL.NET
WithParentActivityOrWindow
Пользовательский интерфейс важен, так как он является интерактивным. AcquireTokenInteractive имеет один конкретный необязательный параметр, который может указывать (для платформ, поддерживающих его) родительского пользовательского интерфейса. При использовании .WithParentActivityOrWindow в классическом приложении он имеет другой тип, который зависит от платформы.
Кроме того, можно опустить необязательный родительский параметр окна для создания окна, если вы не хотите контролировать, где появится диалоговое окно входа на экране. Этот параметр применим для приложений, основанных на командной строке, используется для передачи вызовов любой другой внутренней службе и не требует никаких окон для взаимодействия с пользователем.
// net45 WithParentActivityOrWindow(IntPtr windowPtr) WithParentActivityOrWindow(IWin32Window window) // Mac WithParentActivityOrWindow(NSWindow window) // .NET Standard (this will be on all platforms at runtime, but only on .NET Standard platforms at build time) WithParentActivityOrWindow(object parent).
- В .NET Standard ожидаемое значение находится Activity в Android, в iOS, NSWindow UIViewController в Mac и IWin32Window IntPr в Windows. object
- В Windows необходимо вызвать AcquireTokenInteractive из потока пользовательского интерфейса, чтобы встроенный браузер получил соответствующий контекст синхронизации пользовательского интерфейса. Не вызывая из потока пользовательского интерфейса сообщения, могут неправильно перекачивать сообщения и вызывать сценарии взаимоблокировки с пользовательским интерфейсом. Один из способов вызова библиотеки проверки подлинности Майкрософт (MSAL) из потока пользовательского интерфейса, если вы еще не используете поток пользовательского интерфейса, используется Dispatcher в Windows Presentation Foundation (WPF).
- Если вы используете WPF для получения окна из элемента управления WPF, можно использовать класс WindowInteropHelper.Handle . Затем вызов осуществляется из элемента управления WPF ( this ):
result = await app.AcquireTokenInteractive(scopes) .WithParentActivityOrWindow(new WindowInteropHelper(this).Handle) .ExecuteAsync();
WithPrompt
Вы используете WithPrompt() для управления взаимодействием с пользователем, указав запрос. Точное поведение можно контролировать с помощью структуры Microsoft.Identity.Client.Prompt .
Структура определяет следующие константы:
- SelectAccount заставляет службу маркеров безопасности (STS) представить диалоговое окно выбора учетной записи, содержащее учетные записи, для которых у пользователя есть сеанс. Этот параметр в установлен по умолчанию. Это полезно, если вы хотите разрешить пользователям выбирать между разными удостоверениями. Этот параметр позволяет MSAL отправлять prompt=select_account поставщику удостоверений. Он обеспечивает оптимальный интерфейс на основе доступных сведений, таких как учетная запись и наличие сеанса для пользователя. Не изменяйте его, если у вас нет хорошей причины.
- Consent позволяет принудительно запрашивать согласие пользователя, даже если приложение предоставило согласие. В этом случае MSAL отправляет prompt=consent поставщику удостоверений. Этот параметр можно использовать в некоторых приложениях, ориентированных на безопасность, где управление организации требует, чтобы диалоговое окно согласия отображалось каждый раз, когда пользователь открывает приложение.
- ForceLogin позволяет приложению запрашивать у пользователя учетные данные, даже если этот запрос пользователя может быть не нужен. Этот параметр может быть полезен, чтобы пользователь снова войл в систему, если получение маркера завершается ошибкой. В этом случае MSAL отправляет prompt=login поставщику удостоверений. Организации иногда используют этот параметр в приложениях, ориентированных на безопасность, где управление требует, чтобы пользователи входить каждый раз, когда они обращаются к определенным частям приложения.
- Create активирует процедуру регистрации для внешних удостоверений, отправив prompt=create поставщику удостоверений. Приложения Azure Active Directory B2C (Azure AD B2C) не должны отправлять этот запрос. Дополнительные сведения см. в статье Добавление потока пользователя для самостоятельной регистрации.
- Never (только для .NET 4.5 и среда выполнения Windows) не запрашивает пользователя. Вместо этого он пытается использовать файл cookie, хранящийся в скрытом веб-представлении. Использование этого параметра может завершиться ошибкой. В этом случае вызывает исключение для AcquireTokenInteractive уведомления о необходимости взаимодействия с пользовательским интерфейсом. Затем используйте другой Prompt параметр.
- NoPrompt не отправляет запрос поставщику удостоверений. Поставщик удостоверений решает, какой интерфейс входа лучше всего подходит для пользователя (единый вход или выбор учетной записи). Этот параметр является обязательным для редактирования политик профилей в Azure AD B2C. Дополнительные сведения см. в разделе об особенностях Azure AD B2C.
WithUseEmbeddedWebView
Этот метод позволяет указать, следует ли принудительно использовать внедренный WebView или системный WebView (при наличии). Дополнительные сведения см. в разделе Использование веб-браузеров.
var result = await app.AcquireTokenInteractive(scopes) .WithUseEmbeddedWebView(true) .ExecuteAsync();
WithExtraScopeToConsent
Этот модификатор предназначен для расширенных сценариев, в которых пользователь может предоставить согласие на несколько ресурсов заранее, и вы не хотите использовать добавочное согласие. Разработчики обычно используют добавочное согласие с MSAL.NET и платформа удостоверений Майкрософт. Дополнительные сведения см. в разделе «Согласие пользователя» для нескольких ресурсов.
var result = await app.AcquireTokenInteractive(scopesForCustomerApi) .WithExtraScopeToConsent(scopesForVendorApi) .ExecuteAsync();
WithCustomWebUi
Веб-интерфейс — это механизм для вызова браузера. Этот механизм может быть выделенным элементом управления WebBrowser пользовательского интерфейса или способом делегирования открытия браузера. MSAL предоставляет реализации веб-интерфейса для большинства платформ, но в таких случаях может потребоваться разместить браузер самостоятельно:
- У вас есть платформы, которые MSAL не охватывают явно, например Blazor, Unity и Mono на настольных компьютерах.
- Необходимо протестировать пользовательский интерфейс приложения и использовать автоматизированный браузер, который можно использовать с Selenium.
- Браузер и приложение, в котором выполняется MSAL, находятся в отдельных процессах.
Для этого необходимо предоставить MSAL start Url , который должен отображаться в браузере, чтобы пользователи могли вводить такие элементы, как их имя пользователя. После завершения проверки подлинности приложение должно вернуться в MSAL end Url , который содержит код, который предоставляет идентификатор Microsoft Entra. Узел end Url — это всегда redirectUri . Чтобы перехватить end Url , выполните одно из следующих действий.
- Отслеживайте перенаправления браузера, пока не будет достигнут redirect Url .
- Перенаправьте браузер на url-адрес, который вы отслеживаете.
WithCustomWebUi — это точка расширяемости, которую можно использовать для предоставления собственного пользовательского интерфейса в общедоступных клиентских приложениях. Вы также можете разрешить пользователям пройти /Authorize конечную точку поставщика удостоверений и разрешить им вход и согласие. MSAL.NET может затем активировать код проверки подлинности и получить маркер.
Например, вы можете использовать WithCustomWebUi в Visual Studio приложения Electron (например, Отзывы Visual Studio), предоставляя веб-взаимодействие, но оставьте его MSAL.NET, чтобы сделать большую часть работы. Кроме того, можно использовать WithCustomWebUi , если требуется обеспечить автоматизацию пользовательского интерфейса.
В общедоступных клиентских приложениях MSAL.NET использует стандарт ключа проверки для обмена кодом (PKCE), чтобы обеспечить соблюдение безопасности. Только MSAL.NET может активировать код. Дополнительные сведения см. в разделе RFC 7636 — ключ проверки для обмена кодом с помощью общедоступных клиентов OAuth.
using Microsoft.Identity.Client.Extensions;
Использование WithCustomWebUI
Чтобы использовать WithCustomWebUI , выполните следующие действия.
- Реализуйте интерфейс ICustomWebUi . Дополнительные сведения см . на этой странице GitHub.
- Реализуйте один AcquireAuthorizationCodeAsync метод и примите URL-адрес кода авторизации, который MSAL.NET вычислительных ресурсов.
- Позвольте пользователю пройти взаимодействие с поставщиком удостоверений и вернуть URL-адрес, который поставщик удостоверений использовал для обратного вызова реализации вместе с кодом авторизации. Если у вас возникли проблемы, реализация должна вызвать MsalExtensionException исключение для сотрудничества с MSAL.
- AcquireTokenInteractive В вызове .WithCustomUI() используйте модификатор, передав экземпляр пользовательского веб-интерфейса:
result = await app.AcquireTokenInteractive(scopes) .WithCustomWebUi(yourCustomWebUI) .ExecuteAsync();
Команда MSAL.NET переписала тесты пользовательского интерфейса для использования этого механизма расширяемости. Если вы хотите, просмотрите класс SeleniumWebUI в исходном коде MSAL.NET.
Удобная работа с SystemWebViewOptions
В MSAL.NET 4.1 SystemWebViewOptions можно указать:
- Универсальный код ресурса (URI), на который нужно перейти () или фрагмент HTML для отображения ( BrowserRedirectError HtmlMessageError ), если ошибки входа или согласия отображаются в системном веб-браузере.
- Универсальный код ресурса (URI) для перехода () или фрагмент HTML для отображения ( BrowserRedirectSuccess HtmlMessageSuccess ) при успешном входе или согласии.
- Действие, выполняемое для запуска системного браузера. Вы можете предоставить собственную реализацию, установив делегат OpenBrowserAsync . Класс также предоставляет реализацию по умолчанию для двух браузеров: OpenWithEdgeBrowserAsync для Microsoft Edge и OpenWithChromeEdgeBrowserAsync Microsoft Edge в Chromium.
Чтобы использовать эту структуру, напишите примерно следующий код:
IPublicClientApplication app; . options = new SystemWebViewOptions < HtmlMessageError = "Sign-in failed. You can close this tab . ", BrowserRedirectSuccess = "https://contoso.com/help-for-my-awesome-commandline-tool.html" >; var result = app.AcquireTokenInteractive(scopes) .WithEmbeddedWebView(false) // The default in .NET Core .WithSystemWebViewOptions(options) .Build();
Другие необязательные параметры
Дополнительные сведения о других необязательных параметрах AcquireTokenInteractive см. в статье AcquireTokenInteractiveParameterBuilder.
private static IAuthenticationResult acquireTokenInteractive() throws Exception < // Load the token cache from the file and initialize the token cache aspect. The token cache will have // dummy data, so the acquireTokenSilently call will fail. TokenCacheAspect tokenCacheAspect = new TokenCacheAspect("sample_cache.json"); PublicClientApplication pca = PublicClientApplication.builder(CLIENT_ID) .authority(AUTHORITY) .setTokenCacheAccessAspect(tokenCacheAspect) .build(); SetaccountsInCache = pca.getAccounts().join(); // Take the first account in the cache. In a production application, you would filter // accountsInCache to get the right account for the user who is authenticating. IAccount account = accountsInCache.iterator().next(); IAuthenticationResult result; try < SilentParameters silentParameters = SilentParameters .builder(SCOPE, account) .build(); // try to acquire the token silently. This call will fail because the token cache // does not have any data for the user you're trying to acquire a token for result = pca.acquireTokenSilently(silentParameters).join(); >catch (Exception ex) < if (ex.getCause() instanceof MsalException) < InteractiveRequestParameters parameters = InteractiveRequestParameters .builder(new URI("http://localhost")) .scopes(SCOPE) .build(); // Try to acquire a token interactively with the system browser. If successful, you should see // the token and account information printed out to the console result = pca.acquireToken(parameters).join(); >else < // Handle other exceptions accordingly throw ex; >> return result; >
Код в MSAL для iOS и macOS
MSALInteractiveTokenParameters *interactiveParams = [[MSALInteractiveTokenParameters alloc] initWithScopes:scopes webviewParameters:[MSALWebviewParameters new]]; [application acquireTokenWithParameters:interactiveParams completionBlock:^(MSALResult *result, NSError *error) < if (!error) < // You'll want to get the account identifier to retrieve and reuse the account // for later acquireToken calls NSString *accountIdentifier = result.account.identifier; NSString *accessToken = result.accessToken; >>];
let interactiveParameters = MSALInteractiveTokenParameters(scopes: scopes, webviewParameters: MSALWebviewParameters()) application.acquireToken(with: interactiveParameters, completionBlock: < (result, error) in guard let authResult = result, error == nil else < print(error!.localizedDescription) return >// Get the access token from the result let accessToken = authResult.accessToken >)
На узле MSAL вы приобретаете токены с помощью потока кода авторизации с ключом проверки для обмена кодом (PKCE). Процесс состоит из двух этапов:
- Приложение получает URL-адрес, который можно использовать для создания кода авторизации. Пользователи могут открыть URL-адрес в браузере и ввести свои учетные данные. Затем они перенаправляются обратно redirectUri (зарегистрированы во время регистрации приложения) с кодом авторизации.
- Приложение передает полученный код acquireTokenByCode() авторизации методу, который обменивается им на маркер доступа.
const msal = require("@azure/msal-node"); const msalConfig = < auth: < clientId: "your_client_id_here", authority: "your_authority_here", >>; const pca = new msal.PublicClientApplication(msalConfig); const = await msal.cryptoProvider.generatePkceCodes(); const authCodeUrlParameters = < scopes: ["User.Read"], redirectUri: "your_redirect_uri", codeChallenge: challenge, // PKCE code challenge codeChallengeMethod: "S256" // PKCE code challenge method >; // Get the URL to sign in the user and consent to scopes needed for the application pca.getAuthCodeUrl(authCodeUrlParameters).then((response) => < console.log(response); const tokenRequest = < code: response["authorization_code"], codeVerifier: verifier // PKCE code verifier redirectUri: "your_redirect_uri", scopes: ["User.Read"], >; // Acquire a token by exchanging the code pca.acquireTokenByCode(tokenRequest).then((response) => < console.log("\nResponse: \n:", response); >).catch((error) => < console.log(error); >); >).catch((error) => console.log(JSON.stringify(error)));
MSAL Python 1.7+ предоставляет интерактивный метод получения маркера:
result = None # Check the cache to see if this user has signed in before accounts = app.get_accounts(username=config["username"]) if accounts: result = app.acquire_token_silent(config["scope"], account=accounts[0]) if not result: result = app.acquire_token_interactive( # It automatically provides PKCE protection scopes=config["scope"])
Следующие шаги
Перейдите к следующей статье в этом сценарии, Вызов веб-API из классического приложения.
Введение в Claims-based identity
При разработке приложений на стеке Microsoft для получения информации о текущем пользователе достаточно часто(точнее почти всегда) можно встретить такие участки кода или обертки над ними:
Целью этих вызовов может являться необходимость принятия решения об авторизации вызова какой-то функции или метода, отображение информации о текущем пользователе и тд.
Информация о пользователе появлялась в этих классах разными способами: чтение данных из БД, Forms authentication, NTLM token, Kerberos token. В каждом конкретном случае решалась задача получения информации о пользователе, его аутентификации и получения дополнительной информации.
В “дооблачные времена” этого было вполне достаточно для большинства приложений. Если этого не хватало, то создавались разного рода собственные фреймворки, но во главе угла зачастую стоял главный вопрос: обладает ли пользователь определенной ролью. До определенного момента этого хватало пока хранилище пользователей было одно, не было необходимости взаимодействовать с партнерами по бизнесу и тд. С появлением облаков, распределенных систем, SaaS приложений и других плюшек без которых трудно себе представить современный веб, этой модели стало не хватать, если, к примеру, вы захотели разрешить сотрудникам вашего партнера доступ к определенным функциям вашей CRM. Так же часто встает вопрос развития и эволюционирования приложения, например: изначально вы планировали использовать две группы пользователей User и Administrator и в своем коде щедро раставили авторизационные
атрибуты вида:
[Authorize(«Administrators»)]
public ActionResult DoSomeHardcoreAdminStuff()
.
>
а через год бизнес решил что неплохо было бы иметь несколько различных групп пользователей с разным уровнем доступа и ко всему прочему(ну что бы понять весь драматизм данной ситуации) разграничить права для администраторов на SystemAdministrator и SecurityAdministrator. И это не предел, так как эти требования ограничиваются лишь фантазией бизнеса.
С точки зрения разработчика, все это выливалось в зоопарк технологий и костылей. Каждое приложение аутентифицировало пользователей по-своему. Пользователь мог аутентифицироваться используя OAuth, Forms, Windows или что-нибудь еще. В каждом конкретном случае приходилось писать свою логику аутентификации и авторизации, а если у вас был Api, то еще и для него велосипедик дорисовать.
В ответ на это в 2008 году из недр Microsoft увидел свет первый релиз Windows Identity Foundation(WIF) и была представлена концепция Claims-based identity. Целью этого фреймворка является предоставление абстрактного механизма выражения своих требований к пользователю не углубляясь в детали того, как это работает.
Вкратце идею WIF можно описать достаточно простым жизненным примером:
Вам исполнилось 18 и вы решили сходить в кино. Взрослое кино. Но, к сожалению, не успели получить паспорт или любое другое удостоверение личности до сих пор(ну или просто было лень). Вы собираетесь и идете в паспортный стол, через какое-то время получаете паспорт и, предъявляя ваш паспорт, смело покупаете себе заветный билетик и идете на сеанс. А вот так это выглядит с точки зрения WIF:

Subject, тоесть вы, идете к Identity provider(паспортный стол) и на основе Свидетельство_о_рожденииToken получаете ПасспортToken. Потом, вместе с этим ПасспортToken вы идете к Relying party(кинотеатр) и, после подтверждения вашего возраста, получаете доступ к услуге.
Основные идеи которые можно извлечь из этого примера:
1. Для авторизации вас, как посетителя сеанса для взрослых, кинотеатру не надо вести свою базу клиентов или обращаться куда-либо. Ему достаточно вашего удостоверения личности которому он доверяет(Паспорт, военный билет, права).
2. Паспортный стол не знает где вы будете предъявлять паспорт. (С точки зрения WIF все таки чуточку знать должен, но это не обязательно).
3. С паспортом вы можете купить себе хорошего виски после похода в кино, взять ипотеку или еще что-то в любом учреждении, которое доверяет документам, выданным гос. учреждением.
Кто то уже работал с такими протоколами как OAuth, WS-Trust и WS-Fed, SAML-P и эта схема взаимодействия будет им знакома. Вкратце — информацию о пользователе вы получаете от доверенной удостоверяющей стороны(Identity provider) в виде токена определенного формата и используете ее для принятия каких-либо решений в вашем приложении. В вырожденном случае, например Forms authentication вы сами являетесь этой удостоверяющей стороной и сами же используете эту информацию. WIF допускает такие сценарии. WIF достаточно гибок для поддержки самого разного рода сценариев.
WIF позволяет “аутсорсить” процесс аутентификации доверенной стороне и позволяет свести к минимуму необходимость вмешательство разработчика в процесс аутентификации и авторизации. Все удостоверения, которые предъявляются вашему приложению приводятся к типам ClaimsPrincipal и ClaimsIdentity. Эти типы очень похожи на стандартные *Principal и *Identity, так же реализуют интерфейсы IPrincipal и IIdentity, но имеют дополнительное свойство, которое является коллекцией всех утверждений которые доступны вам о текущем пользователе. Причем для совместимости поддерживаются различные существующие способы работы с IIdentity и IClaimsPrincipal, например:
[PrincipalPermission(SecurityAction.Demand, Role = «Administrators»)]
static void CheckAdministrator()
Console.WriteLine(«User is an administrator»);
>
Для этого достаточно что бы у пользователя было утверждение типа роль( можно настраивать тип утверждений которые будут использоваться как роли) со значением “Administrators”.
В приложение на ASP.NET MVC это может выглядеть так:
[ClaimsAuthorize(ClaimTypes.Role, «Administrators»)]
public ActionResult DoSomeHardcoreAdminStuff()
.
>
[ClaimsAuthorize(ClaimTypes.Permission, «DoSomeHardcoreAdminStuff»)]
public ActionResult DoSomeHardcoreAdminStuff()
.
>
Есть и более сложные сценарии для проверки доступа к тому или иному ресурсу, или просто получение возраста пользователя, его почтового адреса, номера домашнего телефона.
В результате всех этих трансформаций вашему приложению больше не навязывается Role based security подход и вы вольны сами выбирать как, на основание чего и где проводить необходимые проверки, а так же, в части случаев, полностью избавиться от механизмов хранения информации о пользователе внутри приложения. Кроме всего прочего, вы не заботитесь о том, каким способом пользователь прошел аутентификацию, будь это стандартная пара логин-пароль или хитрая смарт карта. Это задача вашего Identity Provider.
На данный момент на платформах от Microsoft есть два основных решения для такого подхода: ADFS(Active Directory Federation Services) и Azure ACS. Если вам не подходит ни то ни другое, то вы вольны самостоятельно написать свой сервис, благо из коробки в студию ставится шаблон с примером. Так же есть опенсорсный сервер IdentityServer на основе которого можно развивать свой собственный продукт.
Из коробки WIF поддерживает следующие протоколы:
1. WS-Federation
2. WS-Trust
3. WS-Security
4. WS-SecurityPolicy
5. WS-Addressing
Поддержка протокола SAML-P находится в состоянии CTP. Информации о RTM версии пока нет. Так же есть OAuth2 extensions.
Стандартно поддерживаются удостоверения SAML1.1 и SAML2. Но уже есть достаточно развитые библиотеки которые добавляют поддержку SWT и даже JWT(Json Web Token).
Это был очень маленький экскурс в то, что происходит в пространстве имен System.Security. В рамках вводного поста не хотелось бы вдаваться в подробности
Кстати в .Net 4.5 Claims-based identity и WIF становятся королем горы. Все типы *Principal будут унаследованы от ClaimsPrincipal, Kerberos токены внутри будут содержать набор утверждений и много чего еще вкусного. Если кому-то интересна эта тема, пишите ваши пожелания в комментариях, как будет время обязательно постараюсь написать.
PS. Спасибо XaocCPS за рецензию.
Общие сведения о Identity ASP.NET Core
Пользователи могут создать учетную запись с данными для входа, хранящимися в Identity ней, или использовать внешний поставщик входа. Поддерживаемые внешние поставщики входа включают Facebook, Google, Учетную запись Майкрософт и Twitter.
Дополнительные сведения о том, как глобально требовать проверку подлинности всех пользователей, см. в разделе Требовать проверку подлинности пользователей.
Исходный Identity код доступен на сайте GitHub. Identity Шаблон и просмотр созданных файлов для просмотра взаимодействия с Identityшаблоном.
Identity обычно настраивается с помощью базы данных SQL Server для хранения имен пользователей, паролей и данных профиля. Кроме того, можно использовать другое постоянное хранилище, например таблицу Azure служба хранилища.
В этом разделе описано, как Identity зарегистрировать, войти и выйти из него. Примечание. Шаблоны обрабатывают имя пользователя и электронную почту так же, как и для пользователей. Дополнительные инструкции по созданию приложений, которые используются Identity, см. в разделе «Дальнейшие действия».
ASP.NET Core Identity не связан с платформа удостоверений Майкрософт. платформа удостоверений Майкрософт:
- Эволюция платформы разработчиков Azure Active Directory (Azure AD).
- Альтернативное решение для идентификации и авторизации в приложениях ASP.NET Core.
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и одностраничные приложения, используйте один из следующих способов:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Компания Duende Software может потребовать лицензионный сбор за использование Duende IdentityServer в рабочей среде. Дополнительные сведения см. в статье Миграция с ASP.NET Core 5.0 на 6.0.
Создание веб-приложения с проверкой подлинности
Создайте проект веб-приложения ASP.NET Core с отдельными учетными записями пользователей.
- Visual Studio
- Интерфейс командной строки .NET Core
- Выберите шаблон Веб-приложение ASP.NET Core. Назовите проект WebApp1 тем же пространством имен, что и скачивание проекта. Щелкните OK.
- В поле входных данных Тип проверки подлинности выберите Отдельные учетные записи пользователей.
dotnet new webapp --auth Individual -o WebApp1
Предыдущая команда создает Razor веб-приложение с помощью SQLite. Чтобы создать веб-приложение с помощью LocalDB, выполните следующую команду:
dotnet new webapp --auth Individual -uld -o WebApp1
Созданный проект предоставляет ASP.NET CoreIdentityв виде библиотеки Razorклассов. Библиотека IdentityRazor классов предоставляет конечные точки с областью Identity . Например:
- /Identity/Account/Login
- /Identity/Account/Logout
- /Identity/Account/Manage
Применение миграции
Примените миграции для инициализации базы данных.
- Visual Studio
- Интерфейс командной строки .NET Core
Выполните следующую команду в консоли диспетчер пакетов (PMC):
Миграция не требуется на этом шаге при использовании SQLite.
Если у вас нет dotnet ef , выполните установку в качестве глобального средства:
dotnet tool install --global dotnet-ef
Дополнительные сведения о интерфейсе командной строки EF Coreсм EF Core . в справочнике по средствам для .NET CLI.
По умолчанию архитектура двоичных файлов .NET для установки представляет архитектуру операционной системы. Чтобы указать другую архитектуру ОС, см . параметр dotnet tool install, —arch. Дополнительные сведения см. в статье о проблеме GitHub dotnet/AspNetCore.Docs #29262.
Для LocalDB выполните следующую команду:
dotnet ef database update
Проверка регистрации и входа
Запустите приложение и зарегистрируйте пользователя. В зависимости от размера экрана может потребоваться выбрать кнопку переключателя навигации, чтобы просмотреть ссылки «Регистрация и вход «.
Identity Просмотр базы данных
- Visual Studio
- Интерфейс командной строки .NET Core
- В меню «Вид» выберите SQL Server обозреватель объектов (SSOX).
- Перейдите к (localdb)MSSQLLocalDB(SQL Server 13). Щелкните правой кнопкой мыши dbo. AspNetUsers>view Data:

Существует множество сторонних средств, которые можно скачать для управления базой данных SQLite и просмотра, например браузер базы данных DB для SQLite.
Настройка Identity служб
Службы добавляются в Program.cs . Типичным шаблоном является вызов методов в следующем порядке:
- Add
- builder.Services.Configure
using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using WebApp1.Data; var builder = WebApplication.CreateBuilder(args); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext(options => options.UseSqlServer(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); builder.Services.AddRazorPages(); builder.Services.Configure(options => < // Password settings. options.Password.RequireDigit = true; options.Password.RequireLowercase = true; options.Password.RequireNonAlphanumeric = true; options.Password.RequireUppercase = true; options.Password.RequiredLength = 6; options.Password.RequiredUniqueChars = 1; // Lockout settings. options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); options.Lockout.MaxFailedAccessAttempts = 5; options.Lockout.AllowedForNewUsers = true; // User settings. options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+"; options.User.RequireUniqueEmail = false; >); builder.Services.ConfigureApplicationCookie(options => < // Cookie settings options.Cookie.HttpOnly = true; options.ExpireTimeSpan = TimeSpan.FromMinutes(5); options.LoginPath = "/Identity/Account/Login"; options.AccessDeniedPath = "/Identity/Account/AccessDenied"; options.SlidingExpiration = true; >); var app = builder.Build(); if (app.Environment.IsDevelopment()) < app.UseMigrationsEndPoint(); >else < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
Предыдущий код настраивается Identity со значениями параметров по умолчанию. Службы становятся доступными для приложения с помощью внедрения зависимостей.
Identity включен путем вызова UseAuthentication. UseAuthentication добавляет ПО промежуточного слоя проверки подлинности в конвейер запросов.
Созданное шаблоном приложение не использует авторизацию. app.UseAuthorization включается, чтобы убедиться, что он добавлен в правильном порядке, если приложение добавит авторизацию. UseRouting , UseAuthentication и UseAuthorization должен вызываться в порядке, приведенном в приведенном выше коде.
Дополнительные сведения см. в IdentityOptions разделе IdentityOptions и запуске приложения.
Шаблон Register, Login, LogOut и RegisterConfirmation
- Visual Studio
- Интерфейс командной строки .NET Core
Если вы создали проект с именем WebApp1, и вы не используете SQLite, выполните следующие команды. В противном случае используйте правильное пространство имен для ApplicationDbContext :
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design dotnet aspnet-codegenerator identity -dc WebApp1.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout;Account.RegisterConfirmation"
При использовании SQLite, добавление —useSqLite или -sqlite :
dotnet aspnet-codegenerator identity -dc WebApp1.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout;Account.RegisterConfirmation" --useSqLite
PowerShell использует точку с запятой в качестве разделителя команд. При использовании PowerShell экранируйте запятую в списке файлов или поместите список файлов в двойные кавычки, как показано в предыдущем примере.
Дополнительные сведения о шаблоне Identityсм. в разделе «Формирование шаблонов» в Razor проект с авторизацией.
Проверка регистра
Когда пользователь нажимает кнопку «Зарегистрировать« на Register странице, RegisterModel.OnPostAsync вызывается действие. Пользователь создается CreateAsync(TUser) в объекте _userManager :
public async Task OnPostAsync(string returnUrl = null) < returnUrl = returnUrl ?? Url.Content("~/"); ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()) .ToList(); if (ModelState.IsValid) < var user = new IdentityUser < UserName = Input.Email, Email = Input.Email >; var result = await _userManager.CreateAsync(user, Input.Password); if (result.Succeeded) < _logger.LogInformation("User created a new account with password."); var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); var callbackUrl = Url.Page( "/Account/ConfirmEmail", pageHandler: null, values: new < area = "Identity", userId = user.Id, code = code >, protocol: Request.Scheme); await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $"Please confirm your account by '>clicking here."); if (_userManager.Options.SignIn.RequireConfirmedAccount) < return RedirectToPage("RegisterConfirmation", new < email = Input.Email >); > else < await _signInManager.SignInAsync(user, isPersistent: false); return LocalRedirect(returnUrl); >> foreach (var error in result.Errors) < ModelState.AddModelError(string.Empty, error.Description); >> // If we got this far, something failed, redisplay form return Page(); >
Отключение проверки учетной записи по умолчанию
При использовании шаблонов по умолчанию пользователь перенаправляется на Account.RegisterConfirmation место, где можно выбрать ссылку, чтобы подтвердить учетную запись. Значение по умолчанию Account.RegisterConfirmation используется только для тестирования, автоматическая проверка учетной записи должна быть отключена в рабочем приложении.
Чтобы требовать подтвержденную учетную запись и предотвратить немедленный вход при регистрации, задайте DisplayConfirmAccountLink = false в /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs :
[AllowAnonymous] public class RegisterConfirmationModel : PageModel < private readonly UserManager_userManager; private readonly IEmailSender _sender; public RegisterConfirmationModel(UserManager userManager, IEmailSender sender) < _userManager = userManager; _sender = sender; >public string Email < get; set; >public bool DisplayConfirmAccountLink < get; set; >public string EmailConfirmationUrl < get; set; >public async Task OnGetAsync(string email, string returnUrl = null) < if (email == null) < return RedirectToPage("/Index"); >var user = await _userManager.FindByEmailAsync(email); if (user == null) < return NotFound($"Unable to load user with email ''."); > Email = email; // Once you add a real email sender, you should remove this code that lets you confirm the account DisplayConfirmAccountLink = false; if (DisplayConfirmAccountLink) < var userId = await _userManager.GetUserIdAsync(user); var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); EmailConfirmationUrl = Url.Page( "/Account/ConfirmEmail", pageHandler: null, values: new < area = "Identity", userId = userId, code = code, returnUrl = returnUrl >, protocol: Request.Scheme); > return Page(); > >
Вход в систему
Форма входа отображается в следующих случаях:
- Выбрана ссылка на вход .
- Пользователь пытается получить доступ к ограниченной странице, к ней не разрешен доступ или когда он не прошел проверку подлинности в системе.
При отправке OnPostAsync формы на странице входа вызывается действие. PasswordSignInAsync вызывается для _signInManager объекта.
public async Task OnPostAsync(string returnUrl = null) < returnUrl = returnUrl ?? Url.Content("~/"); if (ModelState.IsValid) < // This doesn't count login failures towards account lockout // To enable password failures to trigger account lockout, // set lockoutOnFailure: true var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true); if (result.Succeeded) < _logger.LogInformation("User logged in."); return LocalRedirect(returnUrl); >if (result.RequiresTwoFactor) < return RedirectToPage("./LoginWith2fa", new < ReturnUrl = returnUrl, RememberMe = Input.RememberMe >); > if (result.IsLockedOut) < _logger.LogWarning("User account locked out."); return RedirectToPage("./Lockout"); >else < ModelState.AddModelError(string.Empty, "Invalid login attempt."); return Page(); >> // If we got this far, something failed, redisplay form return Page(); >
Сведения о том, как принимать решения об авторизации, см. в разделе «Введение в авторизацию» в ASP.NET Core.
Выход
Ссылка выхода вызывает LogoutModel.OnPost действие.
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; using System.Threading.Tasks; namespace WebApp1.Areas.Identity.Pages.Account < [AllowAnonymous] public class LogoutModel : PageModel < private readonly SignInManager_signInManager; private readonly ILogger _logger; public LogoutModel(SignInManager signInManager, ILogger logger) < _signInManager = signInManager; _logger = logger; >public void OnGet() < >public async Task OnPost(string returnUrl = null) < await _signInManager.SignOutAsync(); _logger.LogInformation("User logged out."); if (returnUrl != null) < return LocalRedirect(returnUrl); >else < return RedirectToPage(); >> > >
В приведенном выше коде код return RedirectToPage(); должен быть перенаправлен, чтобы браузер выполнял новый запрос, а удостоверение пользователя обновляется.
SignOutAsync очищает утверждения пользователя, хранящиеся в объекте cookie.
Запись указана в следующих параметрах Pages/Shared/_LoginPartial.cshtml :
Тест Identity
Шаблоны веб-проектов по умолчанию разрешают анонимный доступ к домашним страницам. Чтобы проверить Identity, добавьте [Authorize] :
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; namespace WebApp1.Pages < [Authorize] public class PrivacyModel : PageModel < private readonly ILogger_logger; public PrivacyModel(ILogger logger) < _logger = logger; >public void OnGet() < >> >
Если вы вошли, выйдите из нее. Запустите приложение и выберите ссылку Privacy . Вы перейдете на страницу входа.
Изучение Identity
Дополнительные сведения см. в следующем Identity разделе:
- Создание полного источника пользовательского интерфейса удостоверения
- Изучите источник каждой страницы и выполните шаг через отладчик.
Identity Components
Все пакеты NuGet, зависящие от зависимогоIdentity, включены в общую платформу ASP.NET Core.
Основной пакет для Identity этого является Microsoft.AspNetCore.Identity. Этот пакет содержит основной набор интерфейсов для ASP.NET Core Identityи включается Microsoft.AspNetCore.Identity.EntityFrameworkCore в него.
Миграция на ASP.NET Core Identity
Дополнительные сведения и рекомендации по переносу существующего Identity хранилища см. в разделе «Миграция проверки подлинности» и Identity»Миграция».
Настройка надежности пароля
См . пример конфигурации , который задает минимальные требования к паролям.
AddDefaultIdentity и AddIdentity
AddDefaultIdentity появилась в ASP.NET Core 2.1. Вызов аналогичен вызову AddDefaultIdentity следующего:
- AddIdentity
- AddDefaultUI
- AddDefaultTokenProviders
Дополнительные сведения см. в источнике AddDefaultIdentity.
Запрет публикации статических Identity ресурсов
Чтобы предотвратить публикацию статических Identity ресурсов (таблиц стилей и файлов JavaScript для Identity пользовательского интерфейса) в корневой веб-сайт, добавьте следующее ResolveStaticWebAssetsInputsDependsOn свойство и RemoveIdentityAssets целевой объект в файл проекта приложения:
RemoveIdentityAssets
Next Steps
- исходный код ASP.NET Core Identity
- Как работать с ролями в ASP.NET Core Identity
- Сведения о настройке Identity с помощью SQLite см. в этой проблеме с GitHub.
- Настройка Identity
- Создание приложения ASP.NET Core с защитой данных пользователя с помощью авторизации
- Добавление, скачивание и удаление пользовательских данных Identity в проект ASP.NET Core
- Включение создания QR-кодов для приложений проверки подлинности TOTP в ASP.NET Core
- Миграция проверки подлинности и Identity ASP.NET Core
- Подтверждение учетной записи и восстановление пароля в ASP.NET Core
- Двухфакторная проверка подлинности с помощью SMS в ASP.NET Core
- Узел ASP.NET Core в веб-ферме
Автор: Рик Андерсон (Rick Anderson)
ASP.NET Core Identity:
- Api, поддерживающий функции входа в пользовательский интерфейс.
- Управляет пользователями, паролями, данными профиля, ролями, утверждениями, маркерами, подтверждением электронной почты и т. д.
Пользователи могут создать учетную запись с данными для входа, хранящимися в Identity ней, или использовать внешний поставщик входа. Поддерживаемые внешние поставщики входа включают Facebook, Google, Учетную запись Майкрософт и Twitter.
Дополнительные сведения о том, как глобально требовать проверку подлинности всех пользователей, см. в разделе Требовать проверку подлинности пользователей.
Исходный Identity код доступен на сайте GitHub. Identity Шаблон и просмотр созданных файлов для просмотра взаимодействия с Identityшаблоном.
Identity обычно настраивается с помощью базы данных SQL Server для хранения имен пользователей, паролей и данных профиля. Кроме того, можно использовать другое постоянное хранилище, например таблицу Azure служба хранилища.
В этом разделе описано, как Identity зарегистрировать, войти и выйти из него. Примечание. Шаблоны обрабатывают имя пользователя и электронную почту так же, как и для пользователей. Дополнительные инструкции по созданию приложений, которые используются Identity, см. в разделе «Дальнейшие действия».
платформа удостоверений Майкрософт:
- Эволюция платформы разработчиков Azure Active Directory (Azure AD).
- Альтернативное решение для идентификации и авторизации в приложениях ASP.NET Core.
- Не связан с ASP.NET Core Identity.
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и одностраничные приложения, используйте один из следующих способов:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende IdentityServer. Duende IdentityServer — это сторонний продукт.
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Дополнительные сведения см. в разделе «Обзор сервера DuendeIdentity».
Дополнительные сведения о других поставщиках проверки подлинности см. в разделе «Параметры проверки подлинности Community OSS» для ASP.NET Core
Создание веб-приложения с проверкой подлинности
Создайте проект веб-приложения ASP.NET Core с отдельными учетными записями пользователей.
- Visual Studio
- Интерфейс командной строки .NET Core
- Выберите File>New>Project ( Файл > Создать > Проект).
- Выберите Веб-приложение ASP.NET Core. Назовите проект WebApp1 тем же пространством имен, что и скачивание проекта. Щелкните OK.
- Выберите веб-приложение ASP.NET Core, а затем нажмите кнопку «Изменить проверку подлинности«.
- Выберите отдельные учетные записи пользователей и нажмите кнопку «ОК«.
dotnet new webapp --auth Individual -o WebApp1
Предыдущая команда создает Razor веб-приложение с помощью SQLite. Чтобы создать веб-приложение с помощью LocalDB, выполните следующую команду:
dotnet new webapp --auth Individual -uld -o WebApp1
Созданный проект предоставляет ASP.NET CoreIdentityв виде библиотеки Razorклассов. Библиотека IdentityRazor классов предоставляет конечные точки с областью Identity . Например:
- /Identity/Account/Login
- /Identity/Account/Logout
- /Identity/Account/Manage
Применение миграции
Примените миграции для инициализации базы данных.
- Visual Studio
- Интерфейс командной строки .NET Core
Выполните следующую команду в консоли диспетчер пакетов (PMC):
Миграция не требуется на этом шаге при использовании SQLite.
Если у вас нет dotnet ef , выполните установку в качестве глобального средства:
dotnet tool install --global dotnet-ef
Дополнительные сведения о интерфейсе командной строки EF Coreсм EF Core . в справочнике по средствам для .NET CLI.
По умолчанию архитектура двоичных файлов .NET для установки представляет архитектуру операционной системы. Чтобы указать другую архитектуру ОС, см . параметр dotnet tool install, —arch. Дополнительные сведения см. в статье о проблеме GitHub dotnet/AspNetCore.Docs #29262.
Для LocalDB выполните следующую команду:
dotnet ef database update
Проверка регистрации и входа
Запустите приложение и зарегистрируйте пользователя. В зависимости от размера экрана может потребоваться выбрать кнопку переключателя навигации, чтобы просмотреть ссылки «Регистрация и вход «.
Identity Просмотр базы данных
- Visual Studio
- Интерфейс командной строки .NET Core
- В меню «Вид» выберите SQL Server обозреватель объектов (SSOX).
- Перейдите к (localdb)MSSQLLocalDB(SQL Server 13). Щелкните правой кнопкой мыши dbo. AspNetUsers>view Data:

Существует множество сторонних средств, которые можно скачать для управления базой данных SQLite и просмотра, например браузер базы данных DB для SQLite.
Настройка Identity служб
Службы добавляются в ConfigureServices . По стандартному шаблону сначала вызываются все методы Add , а затем все методы services.Configure .
public void ConfigureServices(IServiceCollection services) < services.AddDbContext(options => // options.UseSqlite( options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); services.AddRazorPages(); services.Configure(options => < // Password settings. options.Password.RequireDigit = true; options.Password.RequireLowercase = true; options.Password.RequireNonAlphanumeric = true; options.Password.RequireUppercase = true; options.Password.RequiredLength = 6; options.Password.RequiredUniqueChars = 1; // Lockout settings. options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); options.Lockout.MaxFailedAccessAttempts = 5; options.Lockout.AllowedForNewUsers = true; // User settings. options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+"; options.User.RequireUniqueEmail = false; >); services.ConfigureApplicationCookie(options => < // Cookie settings options.Cookie.HttpOnly = true; options.ExpireTimeSpan = TimeSpan.FromMinutes(5); options.LoginPath = "/Identity/Account/Login"; options.AccessDeniedPath = "/Identity/Account/AccessDenied"; options.SlidingExpiration = true; >); >
Предыдущий выделенный код настраивается Identity со значениями параметров по умолчанию. Службы становятся доступными для приложения с помощью внедрения зависимостей.
Identity включен путем вызова UseAuthentication. UseAuthentication добавляет ПО промежуточного слоя проверки подлинности в конвейер запросов.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) < if (env.IsDevelopment()) < app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); >else < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => < endpoints.MapRazorPages(); >); >
public void ConfigureServices(IServiceCollection services) < services.AddDbContext(options => // options.UseSqlite( options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); services.AddDatabaseDeveloperPageExceptionFilter(); services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); services.AddRazorPages(); services.Configure(options => < // Password settings. options.Password.RequireDigit = true; options.Password.RequireLowercase = true; options.Password.RequireNonAlphanumeric = true; options.Password.RequireUppercase = true; options.Password.RequiredLength = 6; options.Password.RequiredUniqueChars = 1; // Lockout settings. options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); options.Lockout.MaxFailedAccessAttempts = 5; options.Lockout.AllowedForNewUsers = true; // User settings. options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+"; options.User.RequireUniqueEmail = false; >); services.ConfigureApplicationCookie(options => < // Cookie settings options.Cookie.HttpOnly = true; options.ExpireTimeSpan = TimeSpan.FromMinutes(5); options.LoginPath = "/Identity/Account/Login"; options.AccessDeniedPath = "/Identity/Account/AccessDenied"; options.SlidingExpiration = true; >); >
Предыдущий код настраивается Identity со значениями параметров по умолчанию. Службы становятся доступными для приложения с помощью внедрения зависимостей.
Identity включен путем вызова UseAuthentication. UseAuthentication добавляет ПО промежуточного слоя проверки подлинности в конвейер запросов.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) < if (env.IsDevelopment()) < app.UseDeveloperExceptionPage(); app.UseMigrationsEndPoint(); >else < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => < endpoints.MapRazorPages(); >); >
Созданное шаблоном приложение не использует авторизацию. app.UseAuthorization включается, чтобы убедиться, что он добавлен в правильном порядке, если приложение добавит авторизацию. UseRouting , UseAuthentication , UseAuthorization и UseEndpoints должен вызываться в порядке, приведенном в предыдущем коде.
Дополнительные сведения и IdentityOptions Startup сведения см. в разделе IdentityOptions » Запуск приложения».
Шаблон Register, Login, LogOut и RegisterConfirmation
- Visual Studio
- Интерфейс командной строки .NET Core
Если вы создали проект с именем WebApp1, и вы не используете SQLite, выполните следующие команды. В противном случае используйте правильное пространство имен для ApplicationDbContext :
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design dotnet aspnet-codegenerator identity -dc WebApp1.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout;Account.RegisterConfirmation"
При использовании SQLite, добавление —useSqLite или -sqlite :
dotnet aspnet-codegenerator identity -dc WebApp1.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout;Account.RegisterConfirmation" --useSqLite
PowerShell использует точку с запятой в качестве разделителя команд. При использовании PowerShell экранируйте запятую в списке файлов или поместите список файлов в двойные кавычки, как показано в предыдущем примере.
Дополнительные сведения о шаблоне Identityсм. в разделе «Формирование шаблонов» в Razor проект с авторизацией.
Проверка регистра
Когда пользователь нажимает кнопку «Зарегистрировать« на Register странице, RegisterModel.OnPostAsync вызывается действие. Пользователь создается CreateAsync(TUser) в объекте _userManager :
public async Task OnPostAsync(string returnUrl = null) < returnUrl = returnUrl ?? Url.Content("~/"); ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()) .ToList(); if (ModelState.IsValid) < var user = new IdentityUser < UserName = Input.Email, Email = Input.Email >; var result = await _userManager.CreateAsync(user, Input.Password); if (result.Succeeded) < _logger.LogInformation("User created a new account with password."); var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); var callbackUrl = Url.Page( "/Account/ConfirmEmail", pageHandler: null, values: new < area = "Identity", userId = user.Id, code = code >, protocol: Request.Scheme); await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $"Please confirm your account by '>clicking here."); if (_userManager.Options.SignIn.RequireConfirmedAccount) < return RedirectToPage("RegisterConfirmation", new < email = Input.Email >); > else < await _signInManager.SignInAsync(user, isPersistent: false); return LocalRedirect(returnUrl); >> foreach (var error in result.Errors) < ModelState.AddModelError(string.Empty, error.Description); >> // If we got this far, something failed, redisplay form return Page(); >
Отключение проверки учетной записи по умолчанию
При использовании шаблонов по умолчанию пользователь перенаправляется на Account.RegisterConfirmation место, где можно выбрать ссылку, чтобы подтвердить учетную запись. Значение по умолчанию Account.RegisterConfirmation используется только для тестирования, автоматическая проверка учетной записи должна быть отключена в рабочем приложении.
Чтобы требовать подтвержденную учетную запись и предотвратить немедленный вход при регистрации, задайте DisplayConfirmAccountLink = false в /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs :
[AllowAnonymous] public class RegisterConfirmationModel : PageModel < private readonly UserManager_userManager; private readonly IEmailSender _sender; public RegisterConfirmationModel(UserManager userManager, IEmailSender sender) < _userManager = userManager; _sender = sender; >public string Email < get; set; >public bool DisplayConfirmAccountLink < get; set; >public string EmailConfirmationUrl < get; set; >public async Task OnGetAsync(string email, string returnUrl = null) < if (email == null) < return RedirectToPage("/Index"); >var user = await _userManager.FindByEmailAsync(email); if (user == null) < return NotFound($"Unable to load user with email ''."); > Email = email; // Once you add a real email sender, you should remove this code that lets you confirm the account DisplayConfirmAccountLink = false; if (DisplayConfirmAccountLink) < var userId = await _userManager.GetUserIdAsync(user); var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); EmailConfirmationUrl = Url.Page( "/Account/ConfirmEmail", pageHandler: null, values: new < area = "Identity", userId = userId, code = code, returnUrl = returnUrl >, protocol: Request.Scheme); > return Page(); > >
Вход в систему
Форма входа отображается в следующих случаях:
- Выбрана ссылка на вход .
- Пользователь пытается получить доступ к ограниченной странице, к ней не разрешен доступ или когда он не прошел проверку подлинности в системе.
При отправке OnPostAsync формы на странице входа вызывается действие. PasswordSignInAsync вызывается для _signInManager объекта.
public async Task OnPostAsync(string returnUrl = null) < returnUrl = returnUrl ?? Url.Content("~/"); if (ModelState.IsValid) < // This doesn't count login failures towards account lockout // To enable password failures to trigger account lockout, // set lockoutOnFailure: true var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true); if (result.Succeeded) < _logger.LogInformation("User logged in."); return LocalRedirect(returnUrl); >if (result.RequiresTwoFactor) < return RedirectToPage("./LoginWith2fa", new < ReturnUrl = returnUrl, RememberMe = Input.RememberMe >); > if (result.IsLockedOut) < _logger.LogWarning("User account locked out."); return RedirectToPage("./Lockout"); >else < ModelState.AddModelError(string.Empty, "Invalid login attempt."); return Page(); >> // If we got this far, something failed, redisplay form return Page(); >
Сведения о том, как принимать решения об авторизации, см. в разделе «Введение в авторизацию» в ASP.NET Core.
Выход
Ссылка выхода вызывает LogoutModel.OnPost действие.
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; using System.Threading.Tasks; namespace WebApp1.Areas.Identity.Pages.Account < [AllowAnonymous] public class LogoutModel : PageModel < private readonly SignInManager_signInManager; private readonly ILogger _logger; public LogoutModel(SignInManager signInManager, ILogger logger) < _signInManager = signInManager; _logger = logger; >public void OnGet() < >public async Task OnPost(string returnUrl = null) < await _signInManager.SignOutAsync(); _logger.LogInformation("User logged out."); if (returnUrl != null) < return LocalRedirect(returnUrl); >else < return RedirectToPage(); >> > >
В приведенном выше коде код return RedirectToPage(); должен быть перенаправлен, чтобы браузер выполнял новый запрос, а удостоверение пользователя обновляется.
SignOutAsync очищает утверждения пользователя, хранящиеся в объекте cookie.
Запись указана в следующих параметрах Pages/Shared/_LoginPartial.cshtml :
Тест Identity
Шаблоны веб-проектов по умолчанию разрешают анонимный доступ к домашним страницам. Чтобы проверить Identity, добавьте [Authorize] :
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; namespace WebApp1.Pages < [Authorize] public class PrivacyModel : PageModel < private readonly ILogger_logger; public PrivacyModel(ILogger logger) < _logger = logger; >public void OnGet() < >> >
Если вы вошли, выйдите из нее. Запустите приложение и выберите ссылку Privacy . Вы перейдете на страницу входа.
Изучение Identity
Дополнительные сведения см. в следующем Identity разделе:
- Создание полного источника пользовательского интерфейса удостоверения
- Изучите источник каждой страницы и выполните шаг через отладчик.
Identity Components
Все пакеты NuGet, зависящие от зависимогоIdentity, включены в общую платформу ASP.NET Core.
Основной пакет для Identity этого является Microsoft.AspNetCore.Identity. Этот пакет содержит основной набор интерфейсов для ASP.NET Core Identityи включается Microsoft.AspNetCore.Identity.EntityFrameworkCore в него.
Миграция на ASP.NET Core Identity
Дополнительные сведения и рекомендации по переносу существующего Identity хранилища см. в разделе «Миграция проверки подлинности» и Identity»Миграция».
Настройка надежности пароля
См . пример конфигурации , который задает минимальные требования к паролям.
Запрет публикации статических Identity ресурсов
Чтобы предотвратить публикацию статических Identity ресурсов (таблиц стилей и файлов JavaScript для Identity пользовательского интерфейса) в корневой веб-сайт, добавьте следующее ResolveStaticWebAssetsInputsDependsOn свойство и RemoveIdentityAssets целевой объект в файл проекта приложения:
RemoveIdentityAssets
Next Steps
- исходный код ASP.NET Core Identity
- Источник AddDefaultIdentity
- Сведения о настройке Identity с помощью SQLite см. в этой проблеме с GitHub.
- Настройка Identity
- Создание приложения ASP.NET Core с защитой данных пользователя с помощью авторизации
- Добавление, скачивание и удаление пользовательских данных Identity в проект ASP.NET Core
- Включение создания QR-кодов для приложений проверки подлинности TOTP в ASP.NET Core
- Миграция проверки подлинности и Identity ASP.NET Core
- Подтверждение учетной записи и восстановление пароля в ASP.NET Core
- Двухфакторная проверка подлинности с помощью SMS в ASP.NET Core
- Узел ASP.NET Core в веб-ферме
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.