教學課程:使用外部租使用者在 .NET MAUI 殼層應用程式中登入使用者
本教學課程是系列的最後一部分,示範如何建立 .NET 多平臺應用程式 UI (.NET MAUI) 殼層應用程式,並準備使用 Microsoft Entra 系統管理中心進行驗證。 在此 系列 的第 2 部分中,您已新增自定義Microsoft驗證連結庫 (MSAL) 客戶端協助程式,以初始化 MSAL SDK、安裝必要的連結庫,並包含映像資源。 最後一個步驟示範如何在 .NET MAUI 中新增登入和註銷程序代碼,並在Android平台上執行殼層應用程式。
在本教學課程中,您將會:
- 新增登入和註銷程序代碼。
- 修改應用程式殼層。
- 新增平臺特定程序代碼。
- 新增應用程式設定。
- 執行及測試 .NET MAUI 殼層應用程式。
必要條件
新增登入和註銷程序代碼
.NET MAUI 應用程式的使用者介面 (UI) 是由對應至每個目標平臺之原生控件的物件所建構。 用來建立 .NET MAUI 應用程式 UI 的主要控件群組是頁面、版面配置和檢視。
新增主檢視頁面
後續步驟會組織我們的程式代碼, main view
以便定義 。
從您的項目刪除 MainPage.xaml 和 MainPage.xaml.cs ,不再需要它們。 在 [方案總管] 窗格中,尋找 MainPage.xaml 的專案,以滑鼠右鍵按兩下它,然後選取 [刪除]。
以滑鼠右鍵按下 SignInMaui 專案,然後選取 [ 新增>資料夾]。 將資料夾 命名為 Views。
以滑鼠右鍵按兩下 [ 檢視]。
選取 [新增>專案...]。
選取 範本清單中的 .NET MAUI 。
選取 .NET MAUI ContentPage (XAML) 範本。 將檔案 命名為 MainView.xaml。
選取 [新增]。
MainView.xaml 檔案將會在新的文件索引標籤開啟,並顯示代表頁面 UI 的所有 XAML 標記。 以下列標記取代 XAML 標記:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SignInMaui.Views.MainView" Title="Microsoft identity platform" > <Shell.BackButtonBehavior> <BackButtonBehavior IsVisible="False" IsEnabled="False" /> </Shell.BackButtonBehavior> <ScrollView> <VerticalStackLayout Spacing="25" Padding="30,0" VerticalOptions="Center"> <Image Source="azure_active_directory.png" SemanticProperties.Description="Azure Active Directory Logo" HeightRequest="200" HorizontalOptions="Center" /> <Label Text="Azure AD for Customers" SemanticProperties.HeadingLevel="Level1" FontSize="26" HorizontalOptions="Center" /> <Label Text="MAUI sample" SemanticProperties.HeadingLevel="Level1" FontSize="26" HorizontalOptions="Center" /> <Button x:Name="SignInButton" Text="Sign In" SemanticProperties.Hint="Sign In" Clicked="OnSignInClicked" HorizontalOptions="Center" IsEnabled="False"/> </VerticalStackLayout> </ScrollView> </ContentPage>
儲存檔案。
讓我們細分放在頁面上之 XAML 控制件的主要部分:
<ContentPage>
是MainView類別的根物件。<VerticalStackLayout>
是 ContentPage 的子物件。 此版面配置控件會垂直排列其子系,一個接一個。<Image>
顯示影像,在此情況下,它會使用您稍早下載的 azureactive_directory.png_ 。<Label>
控件顯示文字。<Button>
使用者可以按下,這會引發Clicked
事件。 您可以執行程式代碼來回應Clicked
事件。Clicked="OnSignInClicked"
Clicked
按鈕的事件會指派給OnSignInClicked
事件處理程式,該事件處理程式會在程式代碼後置檔案中定義。 您將在下一個步驟中建立此程序代碼。
處理 OnSignInClicked 事件
下一個步驟是新增按鈕 Clicked
事件的程序代碼。
在 Visual Studio 的 [方案總管] 窗格中,展開 MainView.xaml 檔案以顯示其程式代碼後置檔案MainView.xaml.cs。 開啟MainView.xaml.cs,並以下列程式代碼取代檔案的內容:
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using SignInMaui.MSALClient; using Microsoft.Identity.Client; namespace SignInMaui.Views { public partial class MainView : ContentPage { public MainView() { InitializeComponent(); IAccount cachedUserAccount = PublicClientSingleton.Instance.MSALClientHelper.FetchSignedInUserFromCache().Result; _ = Dispatcher.DispatchAsync(async () => { if (cachedUserAccount == null) { SignInButton.IsEnabled = true; } else { await Shell.Current.GoToAsync("claimsview"); } }); } private async void OnSignInClicked(object sender, EventArgs e) { await PublicClientSingleton.Instance.AcquireTokenSilentAsync(); await Shell.Current.GoToAsync("claimsview"); } protected override bool OnBackButtonPressed() { return true; } } }
類別
MainView
是負責顯示應用程式主要檢視的內容頁面。 在建構函式中,它會使用MSALClientHelper
實例的PublicClientSingleton
擷取來擷取快取的用戶帳戶,並在找不到任何快取的使用者帳戶時啟用登入按鈕。按兩下登入按鈕時,它會呼叫
AcquireTokenSilentAsync
方法以無訊息方式取得令牌,並使用Shell.Current.GoToAsync
方法巡覽至claimsview
頁面。 此外,會OnBackButtonPressed
覆寫 方法以傳回 true,表示此檢視已停用返回按鈕。
新增宣告檢視頁面
後續步驟會組織程序代碼, ClaimsView
以便定義該頁面。 此頁面會顯示識別元令牌中找到的使用者宣告。
在 Visual Studio 的 [方案總管] 窗格中,以滑鼠右鍵按兩下 [檢視]。
選取 [新增>專案...]。
選取 範本清單中的 .NET MAUI 。
選取 .NET MAUI ContentPage (XAML) 範本。 將檔案命名為 ClaimsView.xaml。
選取 [新增]。
ClaimsView.xaml 檔案將會在新的文件索引標籤中開啟,並顯示代表頁面 UI 的所有 XAML 標記。 以下列標記取代 XAML 標記:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SignInMaui.Views.ClaimsView" Title="ID Token View"> <Shell.BackButtonBehavior> <BackButtonBehavior IsVisible="False" IsEnabled="False" /> </Shell.BackButtonBehavior> <VerticalStackLayout> <Label Text="Azure AD for Customers" FontSize="26" HorizontalOptions="Center" /> <Label Text="MAUI sample" FontSize="26" Padding="0,0,0,20" HorizontalOptions="Center" /> <Label Padding="0,20,0,0" VerticalOptions="Center" HorizontalOptions="Center" FontSize="18" Text="Claims found in ID token" /> <ListView ItemsSource="{Binding IdTokenClaims}" x:Name="Claims"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <Grid Padding="0, 0, 0, 0"> <Label Grid.Column="1" Text="{Binding}" HorizontalOptions="Center" /> </Grid> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> <Button x:Name="SignOutButton" Text="Sign Out" HorizontalOptions="Center" Clicked="SignOutButton_Clicked" /> </VerticalStackLayout> </ContentPage>
此 XAML 標記程式代碼代表 .NET MAUI 應用程式中宣告檢視的 UI 配置。 其一開始是使用標題來定義
ContentPage
,並停用返回按鈕行為。VerticalStackLayout
在 中,有數Label
個ListView
元素顯示靜態文字,後面接著系Claims
結至名為IdTokenClaims
的集合,以顯示在標識元令牌中找到的宣告。 每個宣告都會使用DataTemplate
來轉譯,ViewCell
並顯示為置Label
中方格內。最後,有一個
Sign Out
按鈕置中於版面配置底部,這會在按兩下時觸發SignOutButton_Clicked
事件處理程式。
處理 ClaimsView 數據
下一個步驟是新增程式 ClaimsView
代碼來處理數據。
在 Visual Studio 的 [方案總管] 窗格中,展開 ClaimsView.xaml 檔案以顯示其程式代碼後置檔案ClaimsView.xaml.cs。 開啟ClaimsView.xaml.cs,並以下列程式代碼取代檔案的內容:
using SignInMaui.MSALClient; using Microsoft.Identity.Client; namespace SignInMaui.Views; public partial class ClaimsView : ContentPage { public IEnumerable<string> IdTokenClaims { get; set; } = new string[] {"No claims found in ID token"}; public ClaimsView() { BindingContext = this; InitializeComponent(); _ = SetViewDataAsync(); } private async Task SetViewDataAsync() { try { _ = await PublicClientSingleton.Instance.AcquireTokenSilentAsync(); IdTokenClaims = PublicClientSingleton.Instance.MSALClientHelper.AuthResult.ClaimsPrincipal.Claims.Select(c => c.Value); Claims.ItemsSource = IdTokenClaims; } catch (MsalUiRequiredException) { await Shell.Current.GoToAsync("claimsview"); } } protected override bool OnBackButtonPressed() { return true; } private async void SignOutButton_Clicked(object sender, EventArgs e) { await PublicClientSingleton.Instance.SignOutAsync().ContinueWith((t) => { return Task.CompletedTask; }); await Shell.Current.GoToAsync("mainview"); } }
ClaimsView.xaml.cs程式代碼代表 .NET MAUI 應用程式中宣告檢視的程式代碼後置。 它會從匯入必要的命名空間和定義
ClaimsView
類別開始,這會擴充ContentPage
。 屬性IdTokenClaims
是可列舉的字串,一開始設定為單一字串,表示找不到任何宣告。建構函式會將
ClaimsView
系結內容設定為目前的實例、初始化檢視元件,並以異步方式呼叫SetViewDataAsync
方法。 方法SetViewDataAsync
會嘗試以無訊息方式取得令牌、從驗證結果擷取宣告,並設定IdTokenClaims
屬性以在具名Claims
中ListView
顯示它們。MsalUiRequiredException
如果發生 ,表示驗證需要使用者互動,應用程式會巡覽至宣告檢視。方法
OnBackButtonPressed
會覆寫返回按鈕行為,一律傳回 true,以防止使用者從這個檢視返回。 事件處理程式會SignOutButton_Clicked
使用PublicClientSingleton
實體將使用者登出,並在完成時流覽至main view
。
修改應用程式殼層
類別 AppShell
會定義應用程式的視覺階層,也就是用來建立應用程式 UI 的 XAML 標記。 AppShell
更新 ,讓它知道 Views
。
按兩下
AppShell.xaml
[方案總管] 窗格中的檔案,以開啟 XAML 編輯器。 以下欄程序代碼取代 XAML 標記:<?xml version="1.0" encoding="UTF-8" ?> <Shell x:Class="SignInMaui.AppShell" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:SignInMaui.Views" Shell.FlyoutBehavior="Disabled"> <ShellContent Title="Home" ContentTemplate="{DataTemplate local:MainView}" Route="MainPage" /> </Shell>
XAML 程式代碼會
AppShell
定義類別,該類別會停用飛出視窗行為,並將主要內容設定為ShellContent
具有標題Home
和指向 類別的內容範本的專案MainView
。在 Visual Studio 的 [方案總管] 窗格中,展開 AppShell.xaml 檔案以顯示其程式代碼後置檔案AppShell.xaml.cs。 開啟AppShell.xaml.cs,並以下列程式代碼取代檔案的內容:
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using SignInMaui.Views; namespace SignInMaui; public partial class AppShell : Shell { public AppShell() { InitializeComponent(); Routing.RegisterRoute("mainview", typeof(MainView)); Routing.RegisterRoute("claimsview", typeof(ClaimsView)); } }
您可以更新
AppShell.xaml.cs
檔案,以包含和ClaimsView
的必要路由註冊MainView
。 藉由呼叫InitializeComponent()
方法,您可以確定 類別的AppShell
初始化。 方法會將RegisterRoute()
mainview
和claimsview
路由與其各自的檢視類型產生關聯,MainView
以及ClaimsView
。
新增平臺特定程序代碼
.NET MAUI 應用程式專案包含 [平台] 資料夾,其中每個子資料夾代表 .NET MAUI 可以將其設為目標的平台。 若要提供 Android 應用程式特定行為來補充預設應用程式類別,請遵循下列步驟:
按兩下
Platforms/Android/AndroidManifest.xml
[方案總管] 窗格中的檔案,以開啟 XML 編輯器。 更新下列屬性:- 將 [應用程式名稱] 設定為 MAUI CIAM。
- 將 [套件名稱] 設定為 SignInMaui.Droid。
- 將 [最低 Android 版本] 設定為 [Android 5.0] (API 層級 21)。
按兩下
Platforms/Android/MainActivity.cs
[方案總管] 窗格中的檔案,以開啟 csharp 編輯器。 使用下列程式代碼取代檔案的內容:// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using Android.App; using Android.Content; using Android.Content.PM; using Android.OS; using SignInMaui.MSALClient; using Microsoft.Identity.Client; namespace SignInMaui; [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] public class MainActivity : MauiAppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // configure platform specific params PlatformConfig.Instance.RedirectUri = $"msal{PublicClientSingleton.Instance.MSALClientHelper.AzureAdConfig.ClientId}://auth"; PlatformConfig.Instance.ParentWindow = this; // Initialize MSAL and platformConfig is set _ = Task.Run(async () => await PublicClientSingleton.Instance.MSALClientHelper.InitializePublicClientAppAsync()).Result; } protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data); } }
讓我們細分您已新增之程序代碼的主要部分:
- 必要
using
語句會包含在頂端。 - 類別
MainActivity
是定義,繼承自MauiAppCompatActivity
,這是 .NET MAUI 中 Android 平臺的基類。 - [Activity] 屬性會套用至
MainActivity
類別,並指定 Android 活動的各種設定。Theme = "@style/Maui.SplashTheme"
會設定活動的啟動顯示主題。MainLauncher = true
將此活動指定為應用程式的主要進入點。ConfigurationChanges
指定活動可以處理的組態變更,例如 螢幕大小、 方向、 UI 模式、 螢幕配置、 最小螢幕大小和 密度。
OnCreate
方法會覆寫,以在建立活動時提供自定義邏輯。base.OnCreate(savedInstanceState)
會呼叫 方法的基底實作。PlatformConfig.Instance.RedirectUri
會根據PublicClientSingleton.Instance.MSALClientHelper.AzureAdConfig.ClientId
設定為動態產生的值。 它會設定 MSAL 用戶端的重新導向 URI。PlatformConfig.Instance.ParentWindow
會設定為目前的活動實例,指定驗證相關作業的父視窗。PublicClientSingleton.Instance.MSALClientHelper.InitializePublicClientAppAsync()
使用名為MSALClientHelper
的單一實例的協助程式方法,以異步方式初始化 MSAL 用戶端應用程式。Task.Run
用來在背景線程上執行初始化,並.Result
用來同步等候工作完成。
OnActivityResult
方法會覆寫以處理目前活動所啟動的活動結果。base.OnActivityResult(requestCode, resultCode, data)
會呼叫 方法的基底實作。AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data)
會根據收到的要求碼、結果碼和意圖數據,設定驗證接續事件自變數。 這可用來在外部活動傳回結果之後繼續驗證流程。
- 必要
在 Visual Studio 的 [方案總管] 窗格中,選取 [平臺]。
以滑鼠右鍵按鍵按鍵按鍵夾[新增>專案...]。>
選取 [C# 項目>類別]。 將檔案命名為
MsalActivity.cs
。以下列程式代碼取代檔案的內容
MsalActivity.cs
:// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System; using System.Collections.Generic; using System.Linq; using System.Text; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using Microsoft.Identity.Client; namespace MauiAppBasic.Platforms.Android.Resources { [Activity(Exported =true)] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault }, DataHost = "auth", DataScheme = "msalEnter_the_Application_Id_Here")] public class MsalActivity : BrowserTabActivity { } }
讓我們細分您已新增之程序代碼的主要部分:
MsalActivity
類別是在 命名空間內MauiAppBasic.Platforms.Android.Resources
宣告的。 類別繼承自BrowserTabActivity
類別,表示其擴充功能。- 類別是以 屬性裝飾
[Activity(Exported = true)]
,表示活動已匯出,而且可由其他方法存取。 - 意圖篩選條件是使用 “[IntentFilter(...)]” 屬性來指定。 它會設定活動來攔截
ActionView
意圖。 - 意圖篩選條件設定為使用
ActionView
指定的DataScheme
(msalEnter_the_Application_Id_Here
) 和DataHost
(“auth” 來處理意圖。 此設定可讓活動透過攔截和處理ActionView
意圖來處理驗證程式。 將取代Enter_the_Application_Id_Here
為您 稍早註冊之應用程式的 [應用程式][用戶端] 識別碼 。
新增應用程式設定
設定允許區隔可設定應用程式與程式碼行為的資料,並允許變更行為,而不需要重建應用程式。 MauiAppBuilder
提供ConfigurationManager
在我們的 .NET MAUI 應用程式中設定設定。 讓我們將 appsettings.json
檔案新增為 EmbeddedResource
。
若要建立 appsettings.json
,請遵循下列步驟:
在 Visual Studio 的 [方案總管] 窗格中,以滑鼠右鍵按兩下 SignInMaui 專案 >[新增>專案...]。
選取 [Web>JavaScript JSON 組態檔]。 將檔案命名為
appsettings.json
。選取 [新增]。
選取 appsettings.json
在 [屬性] 窗格中,將 [建置動作] 設定為 [內嵌資源]。
在 [屬性] 窗格中,將 [複製到輸出目錄] 設定為 [一律複製]。
以下列程式代碼取代檔案的內容
appsettings.json
:{ "AzureAd": { "Authority": "https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com/", "ClientId": "Enter_the_Application_Id_Here", "CacheFileName": "msal_cache.txt", "CacheDir": "C:/temp" }, "DownstreamApi": { "Scopes": "openid offline_access" } }
在 中
appsettings.json
,尋找佔位元:Enter_the_Tenant_Subdomain_Here
,並將其取代為目錄 (租用戶) 子網域。 例如,如果您的租用戶主要網域是contoso.onmicrosoft.com
,請使用contoso
。 如果您沒有租用戶名稱,請了解如何閱讀租用戶詳細資料。Enter_the_Application_Id_Here
並將其取代為您稍早註冊的應用程式所使用的應用程式 (用戶端) 識別碼。
使用自訂網域 URL (選擇性 )
使用自定義網域來完整品牌驗證 URL。 從用戶的觀點來看,用戶在驗證程序期間會保留在網域上,而不是重新導向至 ciamlogin.com 功能變數名稱。
請遵循下列步驟來使用自訂網域:
使用為外部租使用者中的應用程式啟用自定義 URL 網域中的步驟,為您的外部租使用者啟用自定義網域 URL。
開啟 appsettings.json 檔案:
- 將屬性的值
Authority
更新為 https://Enter_the_Custom_Domain_Here/Enter_the_Tenant_ID_Here。Enter_the_Custom_Domain_Here
取代為您的自訂網域 URL,並以Enter_the_Tenant_ID_Here
您的租使用者識別碼取代 。 如果您沒有租使用者標識碼,請瞭解如何 閱讀您的租使用者詳細數據。 - 新增
knownAuthorities
具有值 [Enter_the_Custom_Domain_Here] 的屬性。
- 將屬性的值
對appsettings.json檔案進行變更之後,如果您的自定義網域 URL 已 login.contoso.com,且您的租使用者標識符為 aaaabbbb-0000-cccc-1111-dddd2222eeee,則您的檔案看起來應該類似下列代碼段:
{
"AzureAd": {
"Authority": "https://login.contoso.com/aaaabbbb-0000-cccc-1111-dddd2222eeee",
"ClientId": "Enter_the_Application_Id_Here",
"CacheFileName": "msal_cache.txt",
"CacheDir": "C:/temp",
"KnownAuthorities": ["login.contoso.com"]
},
"DownstreamApi": {
"Scopes": "openid offline_access"
}
}
執行及測試 .NET MAUI 行動應用程式
.NET MAUI 應用程式已設計為可在多個作業系統和裝置上執行。 您必須選取目標以用來測試應用程式並進行偵錯。
將 Visual Studio 工具列中的 [偵錯目標] 設定為您想要進行偵錯及測試的裝置。 下列步驟示範將 [ 偵錯目標 ] 設定為 Android:
- 選取 [ 偵錯目標] 下拉式清單。
- 選取 [Android 模擬器]。
- 選取模擬器裝置。
按 F5 或選取 Visual Studio 頂端的「播放按鈕」來執行應用程式。
您現在可以測試範例 .NET MAUI Android 應用程式。 執行應用程式之後,Android 應用程式視窗會出現在模擬器中:
在出現的 Android 視窗中,選取 [ 登入 ] 按鈕。 瀏覽器視窗隨即開啟,系統會提示您登入。
在登入過程中,系統會提示您授與各種權限 (允許應用程式存取您的資料)。 成功登入並同意後,應用程式畫面會顯示主頁面。
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應