Поделиться через


Диспетчер учетных веб-записей

В этой статье описывается, как использовать AccountsSettingsPane для подключения приложения универсальная платформа Windows (UWP) к внешним поставщикам удостоверений, таким как Microsoft или Facebook, с помощью API Диспетчера веб-учетных записей Windows 10 и Windows 11. Вы узнаете, как запросить разрешение пользователя на использование учетной записи Майкрософт, получить маркер доступа и использовать его для выполнения основных операций (например, получения данных профиля или отправки файлов в учетную запись OneDrive). Эти действия аналогичны для получения разрешения пользователя и доступа с любым поставщиком удостоверений, поддерживающим диспетчер веб-учетных записей.

Примечание.

Полный пример кода см. в примере WebAccountManagement на GitHub.

Настройка

Сначала создайте пустое приложение в Visual Studio.

Во-вторых, чтобы подключиться к поставщикам удостоверений, необходимо связать приложение с Магазином. Для этого щелкните проект правой кнопкой мыши, выберите приложение Store/Publish>Associate с магазином и следуйте инструкциям мастера.

В-третьих, создайте очень простой пользовательский интерфейс, состоящий из простой кнопки XAML и двух текстовых полей.

<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
	<Button x:Name="LoginButton" Content="Log in" Click="LoginButton_Click" />
	<TextBlock x:Name="UserIdTextBlock"/>
	<TextBlock x:Name="UserNameTextBlock"/>
</StackPanel>

И обработчик событий, подключенный к кнопке в коде программной части:

private void LoginButton_Click(object sender, RoutedEventArgs e)
{	
}

Наконец, добавьте следующие пространства имен, чтобы вам не нужно беспокоиться о каких-либо справочных проблемах позже:

using System;
using Windows.Security.Authentication.Web.Core;
using Windows.System;
using Windows.UI.ApplicationSettings;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Data.Json;
using Windows.UI.Xaml.Navigation;
using Windows.Web.Http;

Отображение области параметров учетных записей

Система предоставляет встроенный пользовательский интерфейс для управления поставщиками удостоверений и веб-учетными записями с именем AccountsSettingsPane. Вы можете показать следующее:

private void LoginButton_Click(object sender, RoutedEventArgs e)
{
	AccountsSettingsPane.Show(); 
}

Если вы запускаете приложение и нажимаете кнопку "Войти", она должна отобразить пустое окно.

Снимок экрана: окно выбора учетной записи без указанных учетных записей.

Область пуста, так как система предоставляет оболочку пользовательского интерфейса только для разработчика, чтобы программно заполнить область поставщиками удостоверений.

Совет

При необходимости можно использовать ShowAddAccountAsync вместо Show, который вернет IAsyncAction, чтобы запросить состояние операции.

Регистрация для AccountCommandsRequested

Чтобы добавить команды в область, мы начнем с регистрации для обработчика событий AccountCommandsRequested. Это указывает системе запустить логику сборки, когда пользователь просит просмотреть область (например, нажимает кнопку XAML).

В коде позади переопределите события OnNavigatedTo и OnNavigatedFrom и добавьте в них следующий код:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
	AccountsSettingsPane.GetForCurrentView().AccountCommandsRequested += BuildPaneAsync; 
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
	AccountsSettingsPane.GetForCurrentView().AccountCommandsRequested -= BuildPaneAsync; 
}

Пользователи не взаимодействуют с учетными записями очень часто, поэтому регистрация и отмена регистрации обработчика событий в этом режиме помогает предотвратить утечку памяти. Таким образом, настраиваемая область находится только в памяти, если есть высокая вероятность того, что пользователь будет запрашивать его (так как он находится на странице "параметры" или "имя входа", например).

Создание области параметров учетной записи

Метод BuildPaneAsync вызывается всякий раз, когда отображается AccountsSettingsPane . Здесь мы поместим код для настройки команд, отображаемых на панели.

Начните с получения отсрочки. Это сообщает системе отложить отображение AccountsSettingsPane до тех пор, пока мы не завершим сборку.

private async void BuildPaneAsync(AccountsSettingsPane s,
	AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	var deferral = e.GetDeferral();
		
	deferral.Complete(); 
}

Затем получите поставщика с помощью метода WebAuthenticationCoreManager.FindAccountProviderAsync. URL-адрес поставщика зависит от поставщика и можно найти в документации поставщика. Для учетных записей Майкрософт и Azure Active Directory это "https://login.microsoft.com".

private async void BuildPaneAsync(AccountsSettingsPane s,
	AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	var deferral = e.GetDeferral();
		
	var msaProvider = await WebAuthenticationCoreManager.FindAccountProviderAsync(
		"https://login.microsoft.com", "consumers"); 
		
	deferral.Complete(); 
}

Обратите внимание, что мы также передаем строку "потребители" в необязательный параметр центра . Это связано с тем, что корпорация Майкрософт предоставляет два различных типа проверки подлинности — учетные записи Майкрософт (MSA) для "потребителей" и Azure Active Directory (AAD) для "организаций". Центр "потребители" указывает, что нам нужен параметр MSA. Если вы разрабатываете корпоративное приложение, используйте вместо этого строку "организации".

Наконец, добавьте поставщика в AccountsSettingsPane, создав новый WebAccountProviderCommand следующим образом:

private async void BuildPaneAsync(AccountsSettingsPane s,
	AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	var deferral = e.GetDeferral();

	var msaProvider = await WebAuthenticationCoreManager.FindAccountProviderAsync(
		"https://login.microsoft.com", "consumers");

	var command = new WebAccountProviderCommand(msaProvider, GetMsaTokenAsync);  

	e.WebAccountProviderCommands.Add(command);

	deferral.Complete(); 
}

Метод GetMsaToken, переданный в наш новый WebAccountProviderCommand еще не существует (мы создадим его на следующем шаге), поэтому вы можете добавить его в качестве пустого метода на данный момент.

Выполните приведенный выше код, и область должна выглядеть примерно так:

Снимок экрана: окно выбора учетной записи с указанными учетными записями.

Запрос маркера

После того как у нас есть параметр учетной записи Майкрософт, отображаемый в AccountsSettingsPane, необходимо обработать то, что происходит, когда пользователь выбирает его. Мы зарегистрировали наш метод GetMsaToken, чтобы запустить вход с помощью учетной записи Майкрософт, поэтому мы получим маркер там.

Чтобы получить токен, используйте метод RequestTokenAsync, как показано ниже:

private async void GetMsaTokenAsync(WebAccountProviderCommand command)
{
	WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
}

В этом примере мы передаем строку "wl.basic" параметру области . Область представляет тип информации, запрашиваемой от предоставления службы для конкретного пользователя. Некоторые области предоставляют доступ только к основным сведениям пользователя, таким как имя и адрес электронной почты, а другие области могут предоставлять доступ к конфиденциальным данным, таким как фотографии пользователя или почтовые ящики. Как правило, ваше приложение должно использовать наименее разрешительную область, необходимую для достижения ее функции. Поставщики услуг предоставляют документацию по областям, которые необходимы для получения маркеров для использования со своими службами.

Совет

При необходимости, если приложение использует указание для входа (для заполнения поля пользователя адресом электронной почты по умолчанию) или другого специального свойства, связанного с интерфейсом входа, введите его в свойстве WebTokenRequest.AppProperties . Это приведет к тому, что система игнорирует свойство при кэшировании веб-учетной записи, что предотвращает несоответствие учетных записей в кэше.

Если вы разрабатываете корпоративное приложение, скорее всего, вы захотите подключиться к экземпляру Azure Active Directory (AAD) и использовать API Microsoft Graph вместо обычных служб MSA. В этом сценарии используйте следующий код:

private async void GetAadTokenAsync(WebAccountProviderCommand command)
{
	string clientId = "your_guid_here"; // Obtain your clientId from the Azure Portal
	WebTokenRequest request = new WebTokenRequest(provider, "User.Read", clientId);
	request.Properties.Add("resource", "https://graph.microsoft.com");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
}

Остальная часть этой статьи продолжает описывать сценарий MSA, но код для AAD очень похож. Дополнительные сведения об AAD/Graph, включая полный пример на GitHub, см. в документации по Microsoft Graph.

Использование маркера

Метод RequestTokenAsync возвращает объект WebTokenRequestResult, содержащий результаты запроса. Если запрос выполнен успешно, он будет содержать маркер.

private async void GetMsaTokenAsync(WebAccountProviderCommand command)
{
	WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
	
	if (result.ResponseStatus == WebTokenRequestStatus.Success)
	{
		string token = result.ResponseData[0].Token; 
	}
}

Примечание.

Если при запросе маркера возникает ошибка, убедитесь, что вы связали приложение с Магазином, как описано на шаге. Приложение не сможет получить маркер, если вы пропустили этот шаг.

После получения маркера его можно использовать для вызова API поставщика. В приведенном ниже коде мы вызовем api сведений о пользователе Microsoft Live , чтобы получить основные сведения о пользователе и отобразить его в пользовательском интерфейсе. Обратите внимание, что в большинстве случаев рекомендуется хранить маркер после получения, а затем использовать его в отдельном методе.

private async void GetMsaTokenAsync(WebAccountProviderCommand command)
{
	WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
	
	if (result.ResponseStatus == WebTokenRequestStatus.Success)
	{
		string token = result.ResponseData[0].Token; 
		
		var restApi = new Uri(@"https://apis.live.net/v5.0/me?access_token=" + token);

		using (var client = new HttpClient())
		{
			var infoResult = await client.GetAsync(restApi);
			string content = await infoResult.Content.ReadAsStringAsync();

			var jsonObject = JsonObject.Parse(content);
			string id = jsonObject["id"].GetString();
			string name = jsonObject["name"].GetString();

			UserIdTextBlock.Text = "Id: " + id; 
			UserNameTextBlock.Text = "Name: " + name;
		}
	}
}

Способ вызова различных ИНТЕРФЕЙСов REST API зависит от поставщиков; Сведения об использовании маркера см. в документации по API поставщика.

Сохранение учетной записи для дальнейшего использования

Маркеры полезны для немедленного получения сведений о пользователе, но они обычно имеют различные сроки существования — маркеры MSA, например, действительны только в течение нескольких часов. К счастью, вам не нужно повторно отображать AccountsSettingsPane каждый раз, когда истекает срок действия маркера. После того как пользователь авторизовать приложение один раз, вы можете сохранить сведения об учетной записи пользователя для дальнейшего использования.

Для этого используйте класс WebAccount . WebAccount возвращается тем же методом, который использовался для запроса маркера:

private async void GetMsaTokenAsync(WebAccountProviderCommand command)
{
	WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
	
	if (result.ResponseStatus == WebTokenRequestStatus.Success)
	{
		WebAccount account = result.ResponseData[0].WebAccount; 
	}
}

После создания экземпляра WebAccount его можно легко сохранить. В следующем примере мы используем LocalSettings. Дополнительные сведения об использовании LocalSettings и других методах хранения пользовательских данных см. в магазине и получении параметров и данных приложения.

private async void StoreWebAccount(WebAccount account)
{
	ApplicationData.Current.LocalSettings.Values["CurrentUserProviderId"] = account.WebAccountProvider.Id;
	ApplicationData.Current.LocalSettings.Values["CurrentUserId"] = account.Id; 
}

Затем можно использовать асинхронный метод, как показано ниже, чтобы попытаться получить маркер в фоновом режиме с сохраненным WebAccount.

private async Task<string> GetTokenSilentlyAsync()
{
	string providerId = ApplicationData.Current.LocalSettings.Values["CurrentUserProviderId"]?.ToString();
	string accountId = ApplicationData.Current.LocalSettings.Values["CurrentUserId"]?.ToString();

	if (null == providerId || null == accountId)
	{
		return null; 
	}

	WebAccountProvider provider = await WebAuthenticationCoreManager.FindAccountProviderAsync(providerId);
	WebAccount account = await WebAuthenticationCoreManager.FindAccountAsync(provider, accountId);

	WebTokenRequest request = new WebTokenRequest(provider, "wl.basic");

	WebTokenRequestResult result = await WebAuthenticationCoreManager.GetTokenSilentlyAsync(request, account);
	if (result.ResponseStatus == WebTokenRequestStatus.UserInteractionRequired)
	{
		// Unable to get a token silently - you'll need to show the UI
		return null; 
	}
	else if (result.ResponseStatus == WebTokenRequestStatus.Success)
	{
		// Success
		return result.ResponseData[0].Token;
	}
	else
	{
		// Other error 
		return null; 
	}
}

Поместите приведенный выше метод непосредственно перед кодом, который создает AccountsSettingsPane. Если маркер получен в фоновом режиме, не нужно отображать область.

private void LoginButton_Click(object sender, RoutedEventArgs e)
{
	string silentToken = await GetMsaTokenSilentlyAsync();

	if (silentToken != null)
	{
		// the token was obtained. store a reference to it or do something with it here.
	}
	else
	{
		// the token could not be obtained silently. Show the AccountsSettingsPane
		AccountsSettingsPane.Show();
	}
}

Так как автоматическое получение маркера очень просто, этот процесс следует использовать для обновления маркера между сеансами, а не кэширования существующего токена (так как этот маркер может истекать в любое время).

Примечание.

В приведенном выше примере рассматриваются только основные случаи успеха и сбоя. Ваше приложение также должно учитывать необычные сценарии (например, отзыв разрешения пользователя или удаление учетной записи из Windows) и обработать их корректно.

Удаление сохраненной учетной записи

Если вы сохраняете веб-учетную запись, вы можете предоставить пользователям возможность отсоединить свою учетную запись с приложением. Таким образом, они могут эффективно "выйти" из приложения: данные учетной записи больше не будут загружаться автоматически при запуске. Для этого сначала удалите все сохраненные учетные записи и сведения о поставщике из хранилища. Затем вызовите SignOutAsync , чтобы очистить кэш и сделать все существующие маркеры, которые может иметь ваше приложение.

private async Task SignOutAccountAsync(WebAccount account)
{
	ApplicationData.Current.LocalSettings.Values.Remove("CurrentUserProviderId");
	ApplicationData.Current.LocalSettings.Values.Remove("CurrentUserId"); 
	account.SignOutAsync(); 
}

Добавление поставщиков, которые не поддерживают WebAccountManager

Если вы хотите интегрировать проверку подлинности из службы в приложение, но эта служба не поддерживает WebAccountManager — Google+ или Twitter, например, вы можете вручную добавить этого поставщика в AccountsSettingsPane. Для этого создайте новый объект WebAccountProvider и укажите собственное имя и значок .png, а затем добавьте его в список WebAccountProviderCommands. Ниже приведен код заглушки:

private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	// other code here 

	var twitterProvider = new WebAccountProvider("twitter", "Twitter", new Uri(@"ms-appx:///Assets/twitter-auth-icon.png")); 
	var twitterCmd = new WebAccountProviderCommand(twitterProvider, GetTwitterTokenAsync);
	e.WebAccountProviderCommands.Add(twitterCmd);	
	
	// other code here
}

private async void GetTwitterTokenAsync(WebAccountProviderCommand command)
{
	// Manually handle Twitter login here
}

Примечание.

Это добавляет только значок в AccountsSettingsPane и запускает метод, указанный при щелчке значка (GetTwitterTokenAsync, в данном случае). Необходимо указать код, который обрабатывает фактическую проверку подлинности. Дополнительные сведения см. в разделе брокера веб-проверки подлинности, который предоставляет вспомогательные методы проверки подлинности с помощью служб REST.

Добавление настраиваемого заголовка

Панель параметров учетной записи можно настроить с помощью свойства HeaderText, как показано ниже.

private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	// other code here 
	
	args.HeaderText = "MyAwesomeApp works best if you're signed in."; 	
	
	// other code here
}

Снимок экрана: окно

Не перевернуйтесь с текстом заголовка; держать его коротким и сладким. Если процесс входа является сложным и вам нужно отобразить дополнительные сведения, свяжите пользователя с отдельной страницей с помощью настраиваемой ссылки.

Вы можете добавить пользовательские команды в AccountsSettingsPane, которые отображаются в виде ссылок под поддерживаемыми WebAccountProviders. Пользовательские команды отлично подходят для простых задач, связанных с учетными записями пользователей, например отображение политики конфиденциальности или запуск страницы поддержки для пользователей, имеющих проблемы.

Приведем пример:

private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	// other code here 
	
	var settingsCmd = new SettingsCommand(
		"settings_privacy", 
		"Privacy policy", 
		async (x) => await Launcher.LaunchUriAsync(new Uri(@"https://privacy.microsoft.com/en-US/"))); 

	e.Commands.Add(settingsCmd); 
	
	// other code here
}

Снимок экрана: окно выбора учетной записи без указанных учетных записей и ссылка на политику конфиденциальности.

Теоретически можно использовать команды параметров для чего-либо. Однако мы рекомендуем ограничить их использование интуитивно понятными сценариями, связанными с учетной записью, как описано выше.

См. также

Пространство имен Windows.Security.Authentication.Web.Core

Пространство имен Windows.Security.Credentials

Класс AccountsSettingsPane

Брокер веб-аутентификации

Пример управления веб-учетными записями

Приложение планировщика обеда