Udostępnij za pośrednictwem


Samouczek: logowanie użytkowników i wywoływanie programu Microsoft Graph w aplikacji klasycznej Windows Presentation Foundation (WPF)

W tym samouczku utworzysz natywną aplikację platformy .NET dla systemu Windows Desktop (XAML), która loguje użytkowników i uzyskuje token dostępu w celu wywołania interfejsu API programu Microsoft Graph.

Po ukończeniu przewodnika aplikacja będzie mogła wywołać chroniony interfejs API, który używa kont osobistych (w tym outlook.com, live.com i innych). Aplikacja będzie również używać kont służbowych z dowolnej firmy lub organizacji korzystającej z identyfikatora Microsoft Entra.

W tym samouczku:

  • Tworzenie projektu Windows Presentation Foundation (WPF) w programie Visual Studio
  • Instalowanie biblioteki Microsoft Authentication Library (MSAL) dla platformy .NET
  • Rejestrowanie aplikacji
  • Dodawanie kodu do obsługi logowania użytkownika i wylogowywanie się
  • Dodawanie kodu w celu wywołania interfejsu API programu Microsoft Graph
  • Testowanie aplikacji

Wymagania wstępne

Jak działa przykładowa aplikacja wygenerowana przez ten przewodnik

Zrzut ekranu przedstawiający sposób działania przykładowej aplikacji wygenerowanej przez ten samouczek.

Przykładowa aplikacja utworzona za pomocą tego przewodnika umożliwia aplikację klasyczną systemu Windows, która wysyła zapytania do interfejsu API programu Microsoft Graph lub internetowego interfejsu API, który akceptuje tokeny z punktu końcowego Platforma tożsamości Microsoft. W tym scenariuszu dodasz token do żądań HTTP za pośrednictwem nagłówka Autoryzacja. Biblioteka Microsoft Authentication Library (MSAL) obsługuje pozyskiwanie i odnawianie tokenów.

Obsługa uzyskiwania tokenu na potrzeby uzyskiwania dostępu do chronionych internetowych interfejsów API

Po uwierzytelnieniu użytkownika przykładowa aplikacja otrzymuje token, którego można użyć do wykonywania zapytań względem interfejsu API programu Microsoft Graph lub internetowego interfejsu API zabezpieczonego przez Platforma tożsamości Microsoft.

Interfejsy API, takie jak Microsoft Graph, wymagają tokenu umożliwiającego dostęp do określonych zasobów. Na przykład token jest wymagany do odczytywania profilu użytkownika, uzyskiwania dostępu do kalendarza użytkownika lub wysyłania wiadomości e-mail. Aplikacja może zażądać tokenu dostępu przy użyciu biblioteki MSAL w celu uzyskania dostępu do tych zasobów, określając zakresy interfejsu API. Ten token dostępu jest następnie dodawany do nagłówka autoryzacji HTTP dla każdego wywołania wykonanego względem chronionego zasobu.

Biblioteka MSAL zarządza buforowaniem i odświeżaniem tokenów dostępu, aby aplikacja nie musiała tego robić.

Pakiety NuGet

W tym przewodniku są używane następujące pakiety NuGet:

Biblioteka opis
Microsoft.Identity.Client Biblioteka uwierzytelniania firmy Microsoft (MSAL.NET)

konfigurowanie projektu

W tej sekcji utworzysz nowy projekt, aby zademonstrować, jak zintegrować aplikację .NET dla systemu Windows Desktop (XAML) z logowaniem do firmy Microsoft , aby aplikacja mogła wykonywać zapytania dotyczące internetowych interfejsów API, które wymagają tokenu.

Utworzona aplikacja wyświetla przycisk, który będzie wywoływać interfejs API programu Microsoft Graph, obszar do wyświetlania wyników i przycisk wylogowywanie.

Uwaga

Wolisz pobrać zamiast tego projekt programu Visual Studio z tego przykładu? Pobierz projekt i przejdź do kroku Konfiguracja, aby skonfigurować przykładowy kod przed jego wykonaniem.

Utwórz aplikację, wykonując następujące kroki:

  1. Otwórz program Visual Studio.
  2. W oknie uruchamiania wybierz pozycję Utwórz nowy projekt.
  3. Na liście rozwijanej Wszystkie języki wybierz pozycję C#.
  4. Wyszukaj i wybierz szablon Aplikacja WPF (.NET Framework), a następnie wybierz przycisk Dalej.
  5. W polu Nazwa projektu wprowadź nazwę, taką jak Win-App-calling-MsGraph.
  6. Wybierz lokalizację projektu lub zaakceptuj opcję domyślną.
  7. W programie Framework wybierz pozycję .NET Framework 4.8.
  8. Wybierz pozycję Utwórz.

Dodawanie biblioteki MSAL do projektu

  1. W Visual Studio wybierz Narzędzia>NuGet Menedżer pakietów>Konsola menedżera pakietów.

  2. W oknie konsoli Menedżer pakietów wklej następujące polecenie programu Azure PowerShell:

    Install-Package Microsoft.Identity.Client -Pre
    

Rejestrowanie aplikacji

Napiwek

Kroki opisane w tym artykule mogą się nieznacznie różnić w zależności od portalu, od którego zaczynasz.

Aby zarejestrować i skonfigurować aplikację, wykonaj następujące kroki:

  1. Zaloguj się do centrum administracyjnego firmy Microsoft Entra co najmniej jako deweloper aplikacji.
  2. Jeśli masz dostęp do wielu dzierżaw, użyj ikony Ustawienia w górnym menu, aby przełączyć się do dzierżawy, w której chcesz zarejestrować aplikację z menu Katalogi i subskrypcje.
  3. Przejdź do aplikacji tożsamości>> Rejestracje aplikacji.
  4. Wybierz opcjęNowa rejestracja.
  5. Wprowadź nazwę aplikacji, na przykład Win-App-calling-MsGraph. Użytkownicy aplikacji mogą zobaczyć tę nazwę i możesz ją zmienić później.
  6. W sekcji Obsługiwane typy kont wybierz pozycję Konta w dowolnym katalogu organizacyjnym (dowolny katalog Microsoft Entra — multitenant) i osobiste konta Microsoft (np. Skype, Xbox).
  7. Wybierz pozycję Zarejestruj.
  8. W obszarze Zarządzanie wybierz pozycję Uwierzytelnianie>Dodaj platformę.
  9. Wybierz pozycję Aplikacje mobilne i klasyczne.
  10. W sekcji Identyfikatory URI przekierowania wybierz pozycję https://login.microsoftonline.com/common/oauth2/nativeclient.
  11. Wybierz Konfiguruj.

Dodawanie kodu w celu zainicjowania biblioteki MSAL

W tym kroku utworzysz klasę do obsługi interakcji z biblioteką MSAL, taką jak obsługa tokenów.

  1. Otwórz plik App.xaml.cs, a następnie dodaj odwołanie do biblioteki MSAL do klasy:

    using Microsoft.Identity.Client;
    
  2. Zaktualizuj klasę aplikacji do następujących elementów:

    public partial class App : Application
    {
        static App()
        {
            _clientApp = PublicClientApplicationBuilder.Create(ClientId)
                .WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
                .WithDefaultRedirectUri()
                .Build();
        }
    
        // Below are the clientId (Application Id) of your app registration and the tenant information.
        // You have to replace:
        // - the content of ClientID with the Application Id for your app registration
        // - the content of Tenant by the information about the accounts allowed to sign-in in your application:
        //   - For Work or School account in your org, use your tenant ID, or domain
        //   - for any Work or School accounts, use `organizations`
        //   - for any Work or School accounts, or Microsoft personal account, use `common`
        //   - for Microsoft Personal account, use consumers
        private static string ClientId = "Enter_the_Application_Id_here";
    
        private static string Tenant = "common";
    
        private static IPublicClientApplication _clientApp ;
    
        public static IPublicClientApplication PublicClientApp { get { return _clientApp; } }
    }
    

Tworzenie interfejsu użytkownika aplikacji

W tej sekcji pokazano, jak aplikacja może wykonywać zapytania dotyczące chronionego serwera zaplecza, takiego jak Microsoft Graph.

Plik MainWindow.xaml jest tworzony automatycznie jako część szablonu projektu. Otwórz ten plik, a następnie zastąp węzeł Grid> aplikacji <następującym kodem:

<Grid>
    <StackPanel Background="Azure">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
            <Button x:Name="CallGraphButton" Content="Call Microsoft Graph API" HorizontalAlignment="Right" Padding="5" Click="CallGraphButton_Click" Margin="5" FontFamily="Segoe Ui"/>
            <Button x:Name="SignOutButton" Content="Sign-Out" HorizontalAlignment="Right" Padding="5" Click="SignOutButton_Click" Margin="5" Visibility="Collapsed" FontFamily="Segoe Ui"/>
        </StackPanel>
        <Label Content="API Call Results" Margin="0,0,0,-5" FontFamily="Segoe Ui" />
        <TextBox x:Name="ResultText" TextWrapping="Wrap" MinHeight="120" Margin="5" FontFamily="Segoe Ui"/>
        <Label Content="Token Info" Margin="0,0,0,-5" FontFamily="Segoe Ui" />
        <TextBox x:Name="TokenInfoText" TextWrapping="Wrap" MinHeight="70" Margin="5" FontFamily="Segoe Ui"/>
    </StackPanel>
</Grid>

Uzyskiwanie tokenu dla interfejsu API programu Microsoft Graph przy użyciu biblioteki MSAL

W tej sekcji użyjesz biblioteki MSAL do uzyskania tokenu dla interfejsu API programu Microsoft Graph.

  1. W pliku MainWindow.xaml.cs dodaj odwołanie do biblioteki MSAL do klasy:

    using Microsoft.Identity.Client;
    
  2. Zastąp MainWindow kod klasy następującym kodem:

    public partial class MainWindow : Window
    {
        //Set the API Endpoint to Graph 'me' endpoint
        string graphAPIEndpoint = "https://graph.microsoft.com/v1.0/me";
    
        //Set the scope for API call to user.read
        string[] scopes = new string[] { "user.read" };
    
    
        public MainWindow()
        {
            InitializeComponent();
        }
    
      /// <summary>
        /// Call AcquireToken - to acquire a token requiring user to sign-in
        /// </summary>
        private async void CallGraphButton_Click(object sender, RoutedEventArgs e)
        {
            AuthenticationResult authResult = null;
            var app = App.PublicClientApp;
            ResultText.Text = string.Empty;
            TokenInfoText.Text = string.Empty;
    
            var accounts = await app.GetAccountsAsync();
            var firstAccount = accounts.FirstOrDefault();
    
            try
            {
                authResult = await app.AcquireTokenSilent(scopes, firstAccount)
                    .ExecuteAsync();
            }
            catch (MsalUiRequiredException ex)
            {
                // A MsalUiRequiredException happened on AcquireTokenSilent.
                // This indicates you need to call AcquireTokenInteractive to acquire a token
                System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");
    
                try
                {
                    authResult = await app.AcquireTokenInteractive(scopes)
                        .WithAccount(accounts.FirstOrDefault())
                        .WithPrompt(Prompt.SelectAccount)
                        .ExecuteAsync();
                }
                catch (MsalException msalex)
                {
                    ResultText.Text = $"Error Acquiring Token:{System.Environment.NewLine}{msalex}";
                }
            }
            catch (Exception ex)
            {
                ResultText.Text = $"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}";
                return;
            }
    
            if (authResult != null)
            {
                ResultText.Text = await GetHttpContentWithToken(graphAPIEndpoint, authResult.AccessToken);
                DisplayBasicTokenInfo(authResult);
                this.SignOutButton.Visibility = Visibility.Visible;
            }
        }
        }
    

Więcej informacji

Interaktywne pobieranie tokenu użytkownika

AcquireTokenInteractive Wywołanie metody powoduje wyświetlenie okna z monitem o zalogowanie użytkowników. Aplikacje zwykle wymagają, aby użytkownicy logowali się interaktywnie po raz pierwszy, gdy muszą uzyskać dostęp do chronionego zasobu. Może również być konieczne zalogowanie się, gdy operacja dyskretna w celu uzyskania tokenu zakończy się niepowodzeniem (na przykład po wygaśnięciu hasła użytkownika).

Dyskretne pobieranie tokenu użytkownika

Metoda AcquireTokenSilent obsługuje pozyskiwanie i odnawianie tokenów bez interakcji użytkownika. Po AcquireTokenInteractive wykonaniu po raz AcquireTokenSilent pierwszy jest to zwykła metoda, która służy do uzyskiwania tokenów uzyskujących dostęp do chronionych zasobów dla kolejnych wywołań, ponieważ wywołania żądania lub odnawiania tokenów są wykonywane w trybie dyskretnym.

Ostatecznie metoda może zakończyć się niepowodzeniem AcquireTokenSilent . Przyczyną niepowodzenia może być to, że użytkownik wylogował się lub zmienił swoje hasło na innym urządzeniu. Gdy biblioteka MSAL wykryje, że problem można rozwiązać, wymagając interakcyjnej akcji, wyzwala wyjątek MsalUiRequiredException . Aplikacja może obsłużyć ten wyjątek na dwa sposoby:

  • Może natychmiast wykonać wywołanie AcquireTokenInteractive . To wywołanie powoduje wyświetlenie monitu użytkownika o zalogowanie się. Ten wzorzec jest używany w aplikacjach online, w których nie ma dostępnej zawartości offline dla użytkownika. Przykład wygenerowany przez tę konfigurację jest zgodny z tym wzorcem, który można zobaczyć w akcji przy pierwszym wykonaniu przykładu.

  • Ponieważ żaden użytkownik nie użył aplikacji, PublicClientApp.Users.FirstOrDefault() zawiera wartość null i zgłaszany MsalUiRequiredException jest wyjątek.

  • Kod w przykładzie obsługuje następnie wyjątek przez wywołanie AcquireTokenInteractivemetody , co powoduje wyświetlenie monitu użytkownika o zalogowanie się.

  • Zamiast tego może przedstawić użytkownikom wizualne wskazanie, że wymagane jest logowanie interakcyjne, dzięki czemu mogą wybrać odpowiedni czas logowania. Lub aplikacja może ponowić próbę AcquireTokenSilent później. Ten wzorzec jest często używany, gdy użytkownicy mogą korzystać z innych funkcji aplikacji bez zakłóceń. Na przykład gdy zawartość offline jest dostępna w aplikacji. W takim przypadku użytkownicy mogą zdecydować, kiedy chcesz zalogować się, aby uzyskać dostęp do chronionego zasobu lub odświeżyć nieaktualne informacje. Alternatywnie aplikacja może zdecydować się na ponowienie próby po AcquireTokenSilent przywróceniu sieci po tymczasowej niedostępności.

Wywoływanie interfejsu API programu Microsoft Graph przy użyciu właśnie uzyskanego tokenu

Dodaj następującą nową metodę do pliku MainWindow.xaml.cs. Metoda służy do żądania względem interfejsu GET API programu Graph przy użyciu nagłówka Authorize:

/// <summary>
/// Perform an HTTP GET request to a URL using an HTTP Authorization header
/// </summary>
/// <param name="url">The URL</param>
/// <param name="token">The token</param>
/// <returns>String containing the results of the GET operation</returns>
public async Task<string> GetHttpContentWithToken(string url, string token)
{
    var httpClient = new System.Net.Http.HttpClient();
    System.Net.Http.HttpResponseMessage response;
    try
    {
        var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url);
        //Add the token in Authorization header
        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
        response = await httpClient.SendAsync(request);
        var content = await response.Content.ReadAsStringAsync();
        return content;
    }
    catch (Exception ex)
    {
        return ex.ToString();
    }
}

Więcej informacji o tworzeniu wywołania REST względem chronionego interfejsu API

W tej przykładowej aplikacji użyjesz GetHttpContentWithToken metody , aby wysłać żądanie HTTP GET względem chronionego zasobu, który wymaga tokenu, a następnie zwrócić zawartość do obiektu wywołującego. Ta metoda dodaje uzyskany token w nagłówku autoryzacji HTTP. W tym przykładzie zasób jest punktem końcowym interfejsu API me programu Microsoft Graph, który wyświetla informacje o profilu użytkownika.

Dodawanie metody w celu wylogowania użytkownika

Aby wylogować użytkownika, dodaj następującą metodę do pliku MainWindow.xaml.cs :

/// <summary>
/// Sign out the current user
/// </summary>
private async void SignOutButton_Click(object sender, RoutedEventArgs e)
{
    var accounts = await App.PublicClientApp.GetAccountsAsync();

    if (accounts.Any())
    {
        try
        {
            await App.PublicClientApp.RemoveAsync(accounts.FirstOrDefault());
            this.ResultText.Text = "User has signed-out";
            this.CallGraphButton.Visibility = Visibility.Visible;
            this.SignOutButton.Visibility = Visibility.Collapsed;
        }
        catch (MsalException ex)
        {
            ResultText.Text = $"Error signing-out user: {ex.Message}";
        }
    }
}

Więcej informacji na temat wylogowywanie użytkownika

Metoda SignOutButton_Click usuwa użytkowników z pamięci podręcznej użytkownika biblioteki MSAL, co skutecznie informuje bibliotekę MSAL o zapomnieniu bieżącego użytkownika, aby przyszłe żądanie uzyskania tokenu powiodło się tylko wtedy, gdy zostanie wykonane w trybie interaktywnym.

Mimo że aplikacja w tym przykładzie obsługuje pojedynczych użytkowników, biblioteka MSAL obsługuje scenariusze, w których można zalogować wiele kont w tym samym czasie. Przykładem jest aplikacja poczty e-mail, w której użytkownik ma wiele kont.

Wyświetlanie podstawowych informacji o tokenie

Aby wyświetlić podstawowe informacje o tokenie, dodaj następującą metodę do pliku MainWindow.xaml.cs :

/// <summary>
/// Display basic information contained in the token
/// </summary>
private void DisplayBasicTokenInfo(AuthenticationResult authResult)
{
    TokenInfoText.Text = "";
    if (authResult != null)
    {
        TokenInfoText.Text += $"Username: {authResult.Account.Username}" + Environment.NewLine;
        TokenInfoText.Text += $"Token Expires: {authResult.ExpiresOn.ToLocalTime()}" + Environment.NewLine;
    }
}

Więcej informacji

Oprócz tokenu dostępu używanego do wywoływania interfejsu API programu Microsoft Graph po zalogowaniu użytkownika biblioteka MSAL uzyskuje również token identyfikatora. Ten token zawiera niewielki podzbiór informacji, które są istotne dla użytkowników. Metoda DisplayBasicTokenInfo wyświetla podstawowe informacje zawarte w tokenie. Na przykład wyświetla on nazwę wyświetlaną i identyfikator użytkownika, a także datę wygaśnięcia tokenu oraz ciąg reprezentujący sam token dostępu. Możesz wybrać przycisk Wywołaj interfejs API programu Microsoft Graph wiele razy i zobaczyć, że ten sam token został ponownie użyty dla kolejnych żądań. Możesz również zobaczyć, że data wygaśnięcia jest rozszerzona, gdy biblioteka MSAL decyduje, że nadszedł czas na odnowienie tokenu.

testowanie kodu

Aby uruchomić projekt, w programie Visual Studio wybierz pozycję F5. Zostanie wyświetlona aplikacja MainWindow , jak pokazano poniżej:

Przetestuj aplikację.

Przy pierwszym uruchomieniu aplikacji i wybraniu przycisku Wywołaj interfejs API programu Microsoft Graph zostanie wyświetlony monit o zalogowanie. Aby go przetestować, użyj konta Microsoft Entra (konta służbowego) lub konta Microsoft (live.com, outlook.com).

Zaloguj się do aplikacji.

Po pierwszym zalogowaniu się do aplikacji zostanie również wyświetlony monit o wyrażenie zgody na zezwolenie aplikacji na dostęp do profilu i zalogowanie się, jak pokazano poniżej:

Podaj zgodę na dostęp do aplikacji.

Wyświetlanie wyników aplikacji

Po zalogowaniu powinny zostać wyświetlone informacje o profilu użytkownika zwrócone przez wywołanie interfejsu API programu Microsoft Graph. Wyniki są wyświetlane w polu Wyniki wywołań interfejsu API. Podstawowe informacje o tokenie uzyskanym za pośrednictwem wywołania metody AcquireTokenInteractive lub AcquireTokenSilent powinny być widoczne w polu Informacje o tokenie. Wyniki zawierają następujące właściwości:

Właściwości Format opis
Nazwa użytkownika user@domain.com Nazwa użytkownika używana do identyfikowania użytkownika.
Token wygasa DateTime Czas wygaśnięcia tokenu. Biblioteka MSAL rozszerza datę wygaśnięcia, odnawiając token w razie potrzeby.

Więcej informacji o zakresach i uprawnieniach delegowanych

Interfejs API programu Microsoft Graph wymaga zakresu user.read w celu odczytania profilu użytkownika. Ten zakres jest automatycznie dodawany domyślnie w każdej aplikacji zarejestrowanej w portalu rejestracji aplikacji. Inne interfejsy API dla programu Microsoft Graph, a także niestandardowe interfejsy API dla serwera zaplecza, mogą wymagać dodatkowych zakresów. Interfejs API programu Microsoft Graph wymaga zakresu Calendars.Read , aby wyświetlić listę kalendarzy użytkownika.

Aby uzyskać dostęp do kalendarzy użytkownika w kontekście aplikacji, dodaj delegowane uprawnienie Calendars.Read do informacji o rejestracji aplikacji. Następnie dodaj zakres Calendars.Read do wywołania acquireTokenSilent .

Uwaga

Użytkownik może zostać poproszony o dodatkowe zgody w miarę zwiększania liczby zakresów.

Pomoc i obsługa techniczna 

Jeśli potrzebujesz pomocy, chcesz zgłosić problem lub poznać opcje pomocy technicznej, zobacz Pomoc i obsługa techniczna dla deweloperów.

Następny krok

Dowiedz się więcej o tworzeniu aplikacji klasycznych, które nazywają chronione internetowe interfejsy API w naszej serii scenariuszy wieloczęściowych: