Руководство. Вход пользователей в приложение оболочки .NET MAUI с помощью внешнего клиента

В этом руководстве представлена окончательная часть серии, демонстрирующая создание приложения оболочки .NET Multi-platform App UI (.NET MAUI) и подготовка его к проверке подлинности с помощью Центра администрирования Microsoft Entra. В части 2 этой серии вы добавили пользовательский вспомогательный клиент библиотеки проверки подлинности Майкрософт (MSAL), чтобы инициализировать пакет SDK MSAL, установить необходимые библиотеки и включить ресурс образа. На последнем шаге показано, как добавить код входа и выхода в .NET MAUI и запустить приложение оболочки на платформе Android.

В этом руководстве вы выполните следующие действия.

  • Добавьте код входа и выхода.
  • Измените оболочку приложения.
  • Добавьте код для конкретной платформы.
  • Добавьте параметры приложения.
  • Запустите и проверьте приложение оболочки .NET MAUI.

Необходимые компоненты

Добавление кода входа и выхода

Пользовательский интерфейс приложения .NET MAUI создается из объектов, которые сопоставляются с собственными элементами управления каждой целевой платформы. Основными группами элементов управления, используемыми для создания пользовательского интерфейса приложения .NET MAUI, являются страницы, макеты и представления.

Добавление главной страницы представления

Следующие шаги будут упорядочивать наш код таким образом, чтобы main view он был определен.

  1. Удалите MainPage.xaml и MainPage.xaml.cs из проекта, они больше не нужны. В области Обозреватель решений найдите запись для MainPage.xaml, щелкните ее правой кнопкой мыши и выберите "Удалить".

  2. Щелкните правой кнопкой мыши проект SignInMaui и выберите "Добавить>новую папку". Назовите представления папок.

  3. Щелкните правой кнопкой мыши представления.

  4. Выберите "Добавить>новый элемент...".

  5. Выберите .NET MAUI в списке шаблонов.

  6. Выберите шаблон .NET MAUI ContentPage (XAML). Назовите файл MainView.xaml.

  7. Выберите Добавить.

  8. Файл MainView.xaml откроется на новой вкладке документа, отображая всю разметку 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>
    
  9. Сохраните файл.

    Давайте разберем ключевые части элементов управления XAML, размещенные на странице:

    • <ContentPage> — корневой объект для класса MainView.
    • <VerticalStackLayout> является дочерним объектом ContentPage. Этот элемент управления макета упорядочивает дочерние элементы по вертикали, один после другого.
    • <Image> отображает изображение, в этом случае используется azureactive_directory.png_, скачанный ранее.
    • <Label> элементы управления отображают текст.
    • <Button> может нажимать пользователь, который вызывает Clicked событие. Вы можете запустить код в ответ на Clicked событие.
    • Clicked="OnSignInClicked"Clicked Событие кнопки назначается OnSignInClicked обработчику событий, который будет определен в файле кода программной части. Этот код будет создан на следующем шаге.

Обработка события OnSignInClicked

Следующим шагом является добавление кода для события кнопки Clicked .

  1. В области Обозреватель решений 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 — это страница содержимого, отвечающая за отображение основного представления приложения. В конструкторе он извлекает кэшированную учетную запись пользователя с помощью MSALClientHelperPublicClientSingleton экземпляра и включает кнопку входа, если кэшированные учетные записи пользователя не найдены.

    При нажатии кнопки входа метод вызывает AcquireTokenSilentAsync метод автоматического получения маркера и переходит на claimsview страницу с помощью Shell.Current.GoToAsync метода. Кроме того, метод переопределяется для возврата true, указывая, OnBackButtonPressed что кнопка "Назад" отключена для этого представления.

Добавление страницы представления утверждений

Следующие шаги упорядочены в коде, чтобы ClaimsView она была определена. На странице будут отображаться утверждения пользователя, найденные в маркере идентификатора.

  1. В области Обозреватель решений Visual Studio щелкните правой кнопкой мыши представления.

  2. Выберите "Добавить>новый элемент...".

  3. Выберите .NET MAUI в списке шаблонов.

  4. Выберите шаблон .NET MAUI ContentPage (XAML). Назовите файл ClaimsView.xaml.

  5. Выберите Добавить.

  6. Файл ClaimsView.xaml откроется на новой вкладке документа, отображая всю разметку 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. Она начинается с определения ContentPage заголовка и отключения поведения кнопки "Назад".

    VerticalStackLayoutВнутри элемента есть несколько Label элементов, отображающих статический текст, за которым следует ListView именованный Claims элемент, который привязывается к коллекции, вызываемой IdTokenClaims для отображения утверждений, найденных в маркере идентификатора. Каждое утверждение отрисовывается в ViewCell пределах с помощью DataTemplate и отображается в центре Label сетки.

    Наконец, в Sign Out нижней части макета находится кнопка, которая активирует SignOutButton_Clicked обработчик событий при щелчке.

Обработка данных ClaimsView

Следующий шаг — добавить код для обработки ClaimsView данных.

  1. В области Обозреватель решений 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 свойство, отображаемое в именованном ListView виде Claims. MsalUiRequiredException Если происходит, указывая, что взаимодействие с пользователем необходимо для проверки подлинности, приложение переходит к представлению утверждений.

    Метод OnBackButtonPressed переопределяет поведение кнопки "Назад", чтобы всегда возвращать значение true, предотвращая возвращение пользователя из этого представления. Обработчик SignOutButton_Clicked событий подписывает пользователя с помощью экземпляра PublicClientSingleton и после завершения переходит к объекту main view.

Изменение оболочки приложения

Класс AppShell определяет визуальную иерархию приложения, разметку XAML, используемую при создании пользовательского интерфейса приложения. Обновите его AppShell , чтобы сообщить об этом Views.

  1. Дважды щелкните 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 поведение всплывающего элемента и задает основное содержимое элементу с заголовком Home и шаблоном контентаShellContent, указывающим на MainView класс.

  2. В области Обозреватель решений 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 файл, чтобы включить необходимые регистрации маршрутов для MainView и ClaimsView. Вызывая InitializeComponent() метод, необходимо обеспечить инициализацию AppShell класса. Метод связывает и маршруты с соответствующими типами представлений и ClaimsViewMainView .claimsviewmainviewRegisterRoute()

Добавление кода для конкретной платформы

Проект приложения .NET MAUI содержит папку "Платформы" с каждой дочерней папкой, представляющей платформу, которую может выбрать .NET MAUI. Чтобы обеспечить поведение приложения Android для дополнения класса приложений по умолчанию, выполните следующие действия:

  1. Дважды щелкните Platforms/Android/AndroidManifest.xml файл в области Обозреватель решений, чтобы открыть редактор XML. Обновите следующие свойства:

    • Задайте для имени приложения значениеMAUI CIAM.
    • Задайте для именипакета значение SignInMaui.Droid.
    • Установите минимальную версию Android 5.0 (уровень API 21).
  2. Дважды щелкните 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, который является базовым классом для платформы Android в .NET MAUI.
    • Атрибут [Activity] применяется к MainActivity классу, указывая различные параметры для действия Android.
      • Theme = "@style/Maui.SplashTheme" задает тему-заставку для действия.
      • MainLauncher = true обозначает это действие как основную точку входа приложения.
      • ConfigurationChangesуказывает изменения конфигурации, которые может обрабатывать действие, например размер экрана, ориентация, режим пользовательского интерфейса, макет экрана, наименьший размер экрана и плотность.
    • OnCreate метод переопределяется для предоставления пользовательской логики при создании действия.
      • base.OnCreate(savedInstanceState) вызывает базовую реализацию метода.
      • PlatformConfig.Instance.RedirectUri имеет значение динамически созданного значения на PublicClientSingleton.Instance.MSALClientHelper.AzureAdConfig.ClientIdоснове. Он настраивает URI перенаправления для клиента MSAL.
      • PlatformConfig.Instance.ParentWindow имеет значение текущего экземпляра действия, указывающего родительское окно для операций, связанных с проверкой подлинности.
      • PublicClientSingleton.Instance.MSALClientHelper.InitializePublicClientAppAsync() инициализирует клиентское приложение MSAL асинхронно с помощью вспомогательного метода из одноэлементного экземпляра MSALClientHelper. Используется Task.Run для выполнения инициализации в фоновом потоке и .Result используется для синхронного ожидания завершения задачи.
    • OnActivityResult Метод переопределяется для обработки результата действия, запускаемого текущим действием.
      • base.OnActivityResult(requestCode, resultCode, data) вызывает базовую реализацию метода.
      • AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data) задает аргументы события продолжения проверки подлинности на основе полученного кода запроса, кода результата и данных намерений. Он используется для продолжения потока проверки подлинности после возвращения результата внешнего действия.
  3. В области Обозреватель решений Visual Studio выберите платформы.

  4. Щелкните правой кнопкой мыши папку >Android Add>New Item....

  5. Выберите класс элементов>C#. Назовите файл MsalActivity.cs.

  6. Замените содержимое 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, выполните следующие действия.

  1. В области Обозреватель решений Visual Studio щелкните правой кнопкой мыши проект> SignInMaui Add>New Item....

  2. Выберите файл конфигурации JSON web>JavaScript. Назовите файл appsettings.json.

  3. Выберите Добавить.

  4. Выберите appsettings.json

  5. В области "Свойства" задайте значение "Действие сборки" для внедренного ресурса.

  6. В области "Свойства" установите для копирования в выходной каталогвсегда.

  7. Замените содержимое 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"
      }
    }
    
  8. В поле appsettings.json"Найти заполнитель":

    1. Enter_the_Tenant_Subdomain_Here и замените его поддоменом каталога (клиента). Например, если основной домен клиента — это contoso.onmicrosoft.com, используйте contoso. Если у вас нет имени клиента, узнайте, как прочитать сведения о клиенте.
    2. Enter_the_Application_Id_Here и замените его идентификатором приложения (клиента) зарегистрированного ранее приложения.

Запуск и тестирование мобильного приложения .NET MAUI

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

Установите целевой объект отладки на панели инструментов Visual Studio на устройство, с которым требуется выполнить отладку и тестирование. Ниже показано, как задать целевой объект отладки для Android:

  1. Выберите раскрывающийся список "Целевой объект отладки".
  2. Выберите эмуляторы Android.
  3. Выберите устройство эмулятора.

Запустите приложение, нажав клавишу F5 или нажав кнопку воспроизведения в верхней части Visual Studio.

  1. Теперь можно протестировать пример приложения .NET MAUI Android. После запуска приложения окно приложения Android появится в эмуляторе:

    Снимок экрана: кнопка входа в приложение Android.

  2. В появившемся окне Android нажмите кнопку "Войти ". Откроется окно браузера, и вам будет предложено войти.

    Снимок экрана: запрос пользователя на ввод учетных данных в приложении Android.

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

    Снимок экрана: главная страница в приложении Android после входа.

См. также