共用方式為


將驗證新增至 .NET MAUI 應用程式

注意

此產品已淘汰。 如需使用 .NET 8 或更新版本的專案取代專案,請參閱 Community Toolkit Datasync 連結庫

在本教學課程中,您會使用 Microsoft Entra ID,將Microsoft驗證新增至 TodoApp 專案。 完成本教學課程之前,請確定您已 建立專案,並部署後端

提示

雖然我們使用 Microsoft Entra ID 進行驗證,但您可以使用任何您想要與 Azure Mobile Apps 搭配使用的驗證連結庫。

將驗證新增至後端服務

您的後端服務是標準 ASP.NET 6 服務。 任何示範如何啟用 ASP.NET 6 服務驗證與 Azure Mobile Apps 搭配運作的教學課程。

若要為後端服務啟用Microsoft Entra 驗證,您需要:

  • 使用 Microsoft Entra 識別子註冊應用程式。
  • 將驗證檢查新增至 ASP.NET 6 個後端專案。

註冊應用程式

首先,在您的 Microsoft Entra 租用戶中註冊 Web API,並遵循下列步驟來新增範圍:

  1. 登入 Azure 入口網站

  2. 如果您有多個租使用者的存取權,請使用頂端功能表中的 [目錄 + 訂用帳戶] 篩選,切換至您要在其中註冊應用程式的租使用者。

  3. 搜尋並選擇 Microsoft Entra ID

  4. 在 [[管理] 下,選取 [應用程式註冊],>[新增註冊]

    • 名稱:輸入應用程式的名稱;例如,TodoApp 快速入門。 您應用程式的使用者會看到此名稱。 您可以稍後加以變更。
    • 支援的帳戶類型:任何組織目錄中的 帳戶(任何Microsoft Entra 目錄 - 多租使用者)和個人Microsoft帳戶(例如Skype、Xbox)
  5. 選取 [[註冊]。

  6. 在 [管理] 下,選取 [[公開 API>[新增範圍]

  7. 針對 應用程式識別碼 URI,請選取 [儲存並繼續],以接受預設值。

  8. 輸入下列詳細資料:

    • 範圍名稱access_as_user
    • 誰可以同意?系統管理員和使用者
    • 系統管理員同意顯示名稱Access TodoApp
    • 系統管理員同意描述Allows the app to access TodoApp as the signed-in user.
    • 使用者同意顯示名稱Access TodoApp
    • 使用者同意描述Allow the app to access TodoApp on your behalf.
    • 狀態:已啟用
  9. 選取 [[新增範圍],以完成新增範圍。

  10. 請注意範圍的值,類似於 api://<client-id>/access_as_user (稱為 Web API 範圍)。 設定用戶端時,您需要範圍。

  11. 選取 概觀

  12. 請注意 Essentials 區段中的 應用程式 (用戶端) 識別碼 (稱為 Web API 應用程式識別碼)。 您需要此值來設定後端服務。

開啟 Visual Studio,然後選取 TodoAppService.NET6 專案。

  1. 以滑鼠右鍵按下 TodoAppService.NET6 項目,然後選取 [管理 NuGet 套件...

  2. 在新索引標籤中,選取 [流覽],然後在搜尋方塊中輸入 Microsoft.Identity.Web

    在 Visual Studio 中新增 M S A L NuGet 的螢幕快照。

  3. 選擇 Microsoft.Identity.Web 套件,然後按 [安裝]

  4. 請遵循提示來完成套件的安裝。

  5. 開啟 Program.cs。 將下列內容新增至 using 語句清單:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
  1. 將下列程式代碼直接新增至 builder.Services.AddDbContext()呼叫上方:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
  1. 將下列程式代碼直接新增至 app.MapControllers()呼叫上方:
app.UseAuthentication();
app.UseAuthorization();

您的 Program.cs 現在看起來應該像這樣:

using Microsoft.AspNetCore.Datasync;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using TodoAppService.NET6.Db;
  
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
  
if (connectionString == null)
{
  throw new ApplicationException("DefaultConnection is not set");
}
  
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDatasyncControllers();
  
var app = builder.Build();
  
// Initialize the database
using (var scope = app.Services.CreateScope())
{
  var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
  await context.InitializeDatabaseAsync().ConfigureAwait(false);
}
  
// Configure and run the web service.
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
  1. 編輯 Controllers\TodoItemController.cs。 將 [Authorize] 屬性新增至 類別。 您的類別看起來應該像這樣:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Datasync;
using Microsoft.AspNetCore.Datasync.EFCore;
using Microsoft.AspNetCore.Mvc;
using TodoAppService.NET6.Db;

namespace TodoAppService.NET6.Controllers
{
  [Authorize]
  [Route("tables/todoitem")]
  public class TodoItemController : TableController<TodoItem>
  {
    public TodoItemController(AppDbContext context)
      : base(new EntityTableRepository<TodoItem>(context))
    {
    }
  }
}
  1. 編輯 appsettings.json。 新增下列區塊:
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },

<client-id> 取代為您稍早記錄的 Web API 應用程式識別碼。 完成後,看起來應該像這樣:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

再次將您的服務發佈至 Azure:

  1. 以滑鼠右鍵按下 TodoAppService.NET6 項目,然後選取 [[發佈...]
  2. 選取索引標籤右上角的 [[發佈] 按鈕。

開啟瀏覽器以 https://yoursite.azurewebsites.net/tables/todoitem?ZUMO-API-VERSION=3.0.0。 請注意,服務現在會傳回 401 回應,表示需要驗證。

顯示錯誤的瀏覽器螢幕快照。

向身分識別服務註冊您的應用程式

Microsoft數據同步架構內建支援任何在 HTTP 交易標頭內使用 Json Web 令牌 (JWT) 的驗證提供者。 此應用程式會使用 Microsoft 驗證連結庫 (MSAL) 來要求這類令牌,並將登入的使用者授權給後端服務。

設定原生用戶端應用程式

您可以使用用戶端連結庫,例如Microsoft身分識別連結庫(MSAL),註冊原生用戶端,以允許驗證裝載在應用程式中的Web API。

  1. Azure 入口網站中,選取 [Microsoft [專案標識符]>[應用程式註冊]>[新增註冊]

  2. 在 [註冊應用程式 頁面中:

    • 輸入應用程式註冊 名稱。 您可能想要使用名稱 native-quickstart 來區別後端服務所使用的名稱。
    • 選取任何組織目錄中的 帳戶(任何Microsoft Entra 目錄 - 多租使用者)和個人Microsoft帳戶(例如Skype、Xbox)
    • 重新導向 URI
      • 選取 [公用用戶端] [行動裝置 & 桌面]
      • 輸入 URL quickstart://auth
  3. 選取 [[註冊]。

  4. 選取 [API 許可權],>[新增我的 API>的許可權]。

  5. 選取您稍早為後端服務建立的應用程式註冊。 如果您沒有看到應用程式註冊,請確定您已新增 access_as_user 範圍。

    Azure 入口網站中範圍註冊的螢幕快照。

  6. 在 [選取許可權],選取 [access_as_user],然後選取 [[新增許可權]

  7. 選取 [驗證][行動裝置和傳統型應用程式]。

  8. 核取 https://login.microsoftonline.com/common/oauth2/nativeclient旁的方塊。

  9. 核取 msal{client-id}://auth 旁的方塊(以您的應用程式識別碼取代 {client-id})。

  10. 選取 [[新增 URI],然後在字段中新增 http://localhost 以取得額外的 URI。

  11. 選取頁面底部的 [儲存]。

  12. 選取 概觀。 記下 應用程式 (用戶端) 識別碼 (稱為 Native Client Application ID),因為您需要它才能設定行動應用程式。

我們已定義三個重新導向 URL:

  • WPF 應用程式會使用 http://localhost
  • UWP 應用程式會使用 https://login.microsoftonline.com/common/oauth2/nativeclient
  • 行動裝置 (Android 和 iOS) 應用程式會使用 msal{client-id}://auth

將 Microsoft Identity Client 新增至您的應用程式

在 Visual Studio 中開啟 TodoApp.sln 方案,並將 TodoApp.MAUI 項目設定為啟始專案。 將 Microsoft 識別庫 (MSAL) 新增至 TodoApp.MAUI 專案:

Microsoft 識別連結庫 (MSAL) 新增至平台專案:

  1. 以滑鼠右鍵按下項目,然後選取 [管理 NuGet 套件...

  2. 選取 [流覽] 索引標籤。

  3. 在搜尋方塊中輸入 Microsoft.Identity.Client,然後按 Enter 鍵。

  4. 選取 Microsoft.Identity.Client 結果,然後按兩下 [安裝]。

    在Visual Studio中選取 MSAL NuGet 的螢幕快照。

  5. 接受許可協議以繼續安裝。

將原生用戶端標識碼和後端範圍新增至組態。

開啟 TodoApp.Data 項目並編輯 Constants.cs 檔案。 為 ApplicationIdScopes新增常數:

  public static class Constants
  {
      /// <summary>
      /// The base URI for the Datasync service.
      /// </summary>
      public static string ServiceUri = "https://demo-datasync-quickstart.azurewebsites.net";

      /// <summary>
      /// The application (client) ID for the native app within Microsoft Entra ID
      /// </summary>
      public static string ApplicationId = "<client-id>";

      /// <summary>
      /// The list of scopes to request
      /// </summary>
      public static string[] Scopes = new[]
      {
          "<scope>"
      };
  }

<client-id> 取代為您在註冊 Microsoft Entra ID 中註冊用戶端應用程式時收到的 Native Client Application ID,並將 <scope> 取代為您在註冊服務應用程式時 公開 API 時所複製的 Web API 範圍。

TodoApp.MAUI 項目中開啟 MainPage.xaml.cs 類別。 新增下列 using 語句:

using Microsoft.Datasync.Client;
using Microsoft.Identity.Client;
using System.Diagnostics;

MainPage 類別中,新增屬性:

public IPublicClientApplication IdentityClient { get; set; }

調整建構函式以讀取:

public MainPage()
{
    InitializeComponent();
    TodoService = new RemoteTodoService(GetAuthenticationToken);
    viewModel = new MainViewModel(this, TodoService);
    BindingContext = viewModel;
}

GetAuthenticationToken 方法新增至 類別:

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (IdentityClient == null)
    {
#if ANDROID
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .WithParentActivityOrWindow(() => Platform.CurrentActivity)
            .Build();
#elif IOS
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithIosKeychainSecurityGroup("com.microsoft.adalcache")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .Build();
#else
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
            .Build();
#endif
    }

    var accounts = await IdentityClient.GetAccountsAsync();
    AuthenticationResult result = null;
    bool tryInteractiveLogin = false;

    try
    {
        result = await IdentityClient
            .AcquireTokenSilent(Constants.Scopes, accounts.FirstOrDefault())
            .ExecuteAsync();
    }
    catch (MsalUiRequiredException)
    {
        tryInteractiveLogin = true;
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"MSAL Silent Error: {ex.Message}");
    }

    if (tryInteractiveLogin)
    {
        try
        {
            result = await IdentityClient
                .AcquireTokenInteractive(Constants.Scopes)
                .ExecuteAsync();
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"MSAL Interactive Error: {ex.Message}");
        }
    }

    return new AuthenticationToken
    {
        DisplayName = result?.Account?.Username ?? "",
        ExpiresOn = result?.ExpiresOn ?? DateTimeOffset.MinValue,
        Token = result?.AccessToken ?? "",
        UserId = result?.Account?.Username ?? ""
    };
}

GetAuthenticationToken() 方法可與 Microsoft Identity Library (MSAL) 搭配運作,以取得適合將登入使用者授權給後端服務的存取令牌。 接著,此函式會傳遞至 RemoteTodoService 以建立用戶端。 如果驗證成功,就會產生 AuthenticationToken,其中包含授權每個要求所需的數據。 如果沒有,則會改為產生過期的不正確令牌。

我們可以使用具有平台規範的 #if 區域,新增任何平臺特定選項。 例如,Android 需要我們指定從呼叫頁面傳入的父活動。

設定 Android 應用程式以進行驗證

使用下列程式代碼建立新的類別 Platforms\Android\MsalActivity.cs

using Android.App;
using Android.Content;
using Microsoft.Identity.Client;

namespace TodoApp.MAUI
{
    [Activity(Exported = true)]
    [IntentFilter(new[] { Intent.ActionView },
        Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
        DataHost = "auth",
        DataScheme = "msal{client-id}")]
    public class MsalActivity : BrowserTabActivity
    {
    }
}

以原生用戶端的應用程式識別碼取代 {client-id} (這與 Constants.ApplicationId相同)。

如果您的專案以 Android 11 版(API 第 30 版)或更新版本為目標,您必須更新您的 ,以符合Android 套件可見性需求。 開啟 Platforms/Android/AndroidManifest.xml,並將下列 queries/intent 節點新增至 manifest 節點:

<manifest>
  ...
  <queries>
    <intent>
      <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
  </queries>
</manifest>

開啟 MauiProgram.cs。 在檔案頂端包含下列 using 語句:

using Microsoft.Identity.Client;

將產生器更新為下列程式代碼:

    builder
        .UseMauiApp<App>()
        .ConfigureLifecycleEvents(events =>
        {
#if ANDROID
            events.AddAndroid(platform =>
            {
                platform.OnActivityResult((activity, rc, result, data) =>
                {
                    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(rc, result, data);
                });
            });
#endif
        })
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
        });

如果您在更新 iOS 應用程式之後執行此步驟,請新增 #if ANDROID 所指定的程式代碼(包括 #if#endif)。 編譯程式會根據正在編譯的平臺來挑選正確的程式代碼片段。 此程式代碼可以放在iOS的現有區塊之前或之後。

當 Android 需要驗證時,它會取得身分識別客戶端,然後切換至開啟系統瀏覽器的內部活動。 驗證完成後,系統瀏覽器會重新導向至定義的重新導向 URL (msal{client-id}://auth)。 MsalActivity 會擷取重新導向 URL,然後藉由呼叫 OnActivityResult()切換回主要活動。 OnActivityResult() 方法會呼叫 MSAL 驗證協助程式來完成交易。

測試 Android 應用程式

TodoApp.MAUI 設定為啟始專案,選取 android 模擬器作為目標,然後按 F5 來建置並執行應用程式。 當應用程式啟動時,系統會提示您登入應用程式。 在第一次執行時,系統會要求您同意應用程式。 驗證完成後,應用程式會正常執行。

測試 Windows 應用程式

TodoApp.MAUI 設定為啟始專案,選取 [Windows Machine 作為目標,然後按 F5 來建置並執行應用程式。 當應用程式啟動時,系統會提示您登入應用程式。 在第一次執行時,系統會要求您同意應用程式。 驗證完成後,應用程式會正常執行。

後續步驟

接下來,實作離線存放區,設定您的應用程式以離線運作。

進一步閱讀