背水一戰 Windows 10 (84) - 用戶和賬號: 微軟賬號的登錄和注銷
作者:webabcd
介紹
背水一戰 Windows 10 之 用戶和賬號
- 微軟賬號的登錄和注銷
示例
演示如何將微軟賬號的登錄和注銷集成到 app 中
UserAndAccount/MicrosoftAccount.xaml
<Page x:Class="Windows10.UserAndAccount.MicrosoftAccount" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.UserAndAccount" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <Button Name="button" Content="登錄/注銷" Margin="5" Click="button_Click" /> <TextBlock Name="lblMsg" Margin="5" /> <Ellipse Width="48" Height="48" HorizontalAlignment="Left" Margin="5"> <Ellipse.Fill> <ImageBrush x:Name="imagePicture" /> </Ellipse.Fill> </Ellipse> </StackPanel> </Grid> </Page>
UserAndAccount/MicrosoftAccount.xaml.cs
/* * 演示如何將微軟賬號的登錄和注銷集成到 app 中 * * AccountsSettingsPane - 賬號配置界面 * Show() - 彈出界面 * GetForCurrentView() - 獲取當前的 AccountsSettingsPane 實例 * AccountCommandsRequested - 彈出界面時觸發的事件(事件參數為:AccountsSettingsPaneCommandsRequestedEventArgs) * * AccountsSettingsPaneCommandsRequestedEventArgs * GetDeferral() - 獲取異步操作對象 * HeaderText - 彈出界面上需要顯示的標題文字 * Commands - 返回一個 SettingsCommand 列表,用於在界面上添加自定義按鈕 * * * * 流程簡述: * * 登錄第一步,將指定的 web 賬號提供商添加到賬號登錄界面中 * WebAccountProvider - web 賬號提供商(本例以微軟賬號為例) * WebAuthenticationCoreManager - 用於獲取指定的 WebAccountProvider * WebAccountProviderCommand - 用於將指定的 WebAccountProvider 添加到賬號登錄界面中 * * 登錄第二步,用戶在賬號登錄界面中登錄后 * WebTokenRequest - 通過指定的 WebAccountProvider 獲取這個 web 請求對象 * WebTokenRequestResult - 通過 WebAuthenticationCoreManager 和指定的 WebTokenRequest 獲取這個 web 請求結果 * * 注銷第一步,將指定的 web 賬號添加到賬號管理界面中 * WebAccount - 通過 WebAuthenticationCoreManager 和指定的 WebAccountProvider 和指定的 userId 獲取這個 web 賬號對象 * WebAccountCommand - 用於將指定的 WebAccount 添加到賬號管理界面中 * * 注銷第二步,用戶在賬號管理界面中選擇注銷后 * WebAccount - 可以調用這個對象的注銷方法 * * * * 注: * 本例測試時會報 ProviderError 錯誤,因為“you must register your app under the Microsoft Store with a Microsoft developer account” * 給自己一個提醒,如果需要看效果的話,請參見自己寫的“打字通”app 中的 MicrosoftAccount.xaml */ using System; using System.Net.Http; using System.Threading.Tasks; using Windows.Data.Json; using Windows.Security.Authentication.Web.Core; using Windows.Security.Credentials; using Windows.UI.ApplicationSettings; using Windows.UI.Popups; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Navigation; namespace Windows10.UserAndAccount { public sealed partial class MicrosoftAccount : Page { const string MicrosoftAccountProviderId = "https://login.microsoft.com"; const string ConsumerAuthority = "consumers"; const string AccountScopeRequested = "wl.basic"; const string AccountClientId = "none"; private string _userId = null; public MicrosoftAccount() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); // 彈出賬號配置界面時觸發的事件 AccountsSettingsPane.GetForCurrentView().AccountCommandsRequested += OnAccountCommandsRequested; } protected override void OnNavigatedFrom(NavigationEventArgs e) { base.OnNavigatedFrom(e); AccountsSettingsPane.GetForCurrentView().AccountCommandsRequested -= OnAccountCommandsRequested; } private void button_Click(object sender, RoutedEventArgs e) { // 彈出賬號配置界面 AccountsSettingsPane.Show(); } private async void OnAccountCommandsRequested(AccountsSettingsPane sender, AccountsSettingsPaneCommandsRequestedEventArgs e) { AccountsSettingsPaneEventDeferral deferral = e.GetDeferral(); if (_userId == null) { // 彈出賬號配置界面用於賬號登錄 await ShowLoginUI(e); // 彈出界面上需要顯示的標題文字 e.HeaderText = "請登錄"; } else { // 彈出賬號配置界面用於賬號管理(本例用於演示注銷) await ShowLogoutUI(e); // 彈出界面上需要顯示的標題文字 e.HeaderText = "請注銷"; } // 在彈出界面上添加自定義按鈕 e.Commands.Add(new SettingsCommand("help", "幫助", HelpInvoked)); e.Commands.Add(new SettingsCommand("about", "關於", AboutInvoked)); deferral.Complete(); } private void HelpInvoked(IUICommand command) { lblMsg.Text = "用戶點擊了“幫助”按鈕"; } private void AboutInvoked(IUICommand command) { lblMsg.Text = "用戶點擊了“關於”按鈕"; } // 將指定的 web 賬號提供商添加到賬號登錄界面中 private async Task ShowLoginUI(AccountsSettingsPaneCommandsRequestedEventArgs e) { WebAccountProvider provider = await WebAuthenticationCoreManager.FindAccountProviderAsync(MicrosoftAccountProviderId, ConsumerAuthority); WebAccountProviderCommand providerCommand = new WebAccountProviderCommand(provider, WebAccountProviderCommandInvoked); e.WebAccountProviderCommands.Add(providerCommand); } // 用戶在賬號登錄界面中登錄后 private async void WebAccountProviderCommandInvoked(WebAccountProviderCommand command) { try { WebTokenRequest webTokenRequest = new WebTokenRequest(command.WebAccountProvider, AccountScopeRequested, AccountClientId); WebTokenRequestResult webTokenRequestResult = await WebAuthenticationCoreManager.RequestTokenAsync(webTokenRequest); if (webTokenRequestResult.ResponseStatus == WebTokenRequestStatus.Success) { var response = webTokenRequestResult.ResponseData[0]; if (response != null) { // 拿到 userId,實際開發中一般會將此信息保存到本地 string userId = response.WebAccount.Id; _userId = userId; lblMsg.Text = "登錄成功,userId:" + userId; lblMsg.Text += Environment.NewLine; /* * 微軟賬號的登錄過程到此就完成了 * 如果想通過 response.WebAccount.UserName 這種方式來獲取賬號的用戶名或其他信息的話,那是獲取不到的 * 需要帶着 response.Token 去請求 apis.live.net 來獲取相關信息,說明如下 */ // 登錄成功后,要通過拿到的 token 像下面這樣獲取用戶信息 var restApi = new Uri(@"https://apis.live.net/v5.0/me?access_token=" + response.Token); using (var client = new HttpClient()) { var infoResult = await client.GetAsync(restApi); string content = await infoResult.Content.ReadAsStringAsync(); /* 獲取到的內容類似如下 { "id": "abcd1234abcd1234", "name": "王磊", "first_name": "磊", "last_name": "王", "link": "https://profile.live.com/", "gender": null, "locale": "zh_CN", "updated_time": "2017-04-27T02:24:58+0000" } */ var jsonObject = JsonObject.Parse(content); string name = jsonObject["name"].GetString() ?? ""; string locale = jsonObject["locale"].GetString() ?? ""; lblMsg.Text += $"name:{name}, locale:{locale}"; // 通過如下方式拿到用戶圖片 string profileId = jsonObject["id"].GetString() ?? ""; string pictureUrl = $"https://apis.live.net/v5.0/{profileId}/picture" ?? ""; imagePicture.ImageSource = new BitmapImage(new Uri(pictureUrl)); } } } else { lblMsg.Text = "登錄失敗:" + webTokenRequestResult.ResponseStatus.ToString(); } } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } // 將指定的 web 賬號添加到賬號管理界面中 private async Task ShowLogoutUI(AccountsSettingsPaneCommandsRequestedEventArgs e) { WebAccountProvider provider = await WebAuthenticationCoreManager.FindAccountProviderAsync(MicrosoftAccountProviderId, ConsumerAuthority); WebAccount account = await WebAuthenticationCoreManager.FindAccountAsync(provider, _userId); if (account != null) { // 最后一個參數用於指定當用戶選擇了賬號后,會出現哪些功能按鈕(我這里測試只有 SupportedWebAccountActions.Remove 是有效的) WebAccountCommand command = new WebAccountCommand(account, WebAccountCommandInvoked, SupportedWebAccountActions.Remove); e.WebAccountCommands.Add(command); } else { _userId = null; } } // 用戶在賬號管理界面中選擇了某項功能 private async void WebAccountCommandInvoked(WebAccountCommand command, WebAccountInvokedArgs args) { // 用戶選擇的是注銷 if (args.Action == WebAccountAction.Remove) { await command.WebAccount.SignOutAsync(); _userId = null; lblMsg.Text = "注銷成功"; imagePicture.ImageSource = null; } } } }
OK
[源碼下載]