你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

如果在应用中使用 Microsoft 身份验证库 (MSAL) 进行身份验证

若要以编程方式对群集进行身份验证,需要从特定于 Azure 数据资源管理器 的Microsoft Entra ID 请求访问令牌。 在向群集发出请求时,此访问令牌充当身份证明。 可使用 Microsoft 身份验证库 (MSAL)之一来创建访问令牌。

本文介绍如何使用 MSAL 对群集的主体进行身份验证。 直接使用 MSAL 对主体进行身份验证主要适用于需要代理 (OBO) 身份验证单页应用程序 (SPA) 身份验证的 Web 应用程序。 对于其他情况,建议使用 Kusto 客户端库,因为它们简化了身份验证过程。

在本文中,了解主要的身份验证场景、为成功通过身份验证而提供的信息,以及使用 MSAL 进行身份验证的情况。

身份验证方案

主要身份验证场景如下所示:

对于用户和应用程序身份验证,建议使用 Kusto 客户端库。 对于 OBO 和 SPA 身份验证,不能使用 Kusto 客户端库。

身份验证参数

在令牌获取过程中,客户端需要提供以下参数:

参数名称 说明
资源 ID 要为其颁发Microsoft Entra访问令牌的资源 ID。 资源 ID 是不包含端口信息和路径的群集 URI。

示例:help 群集的资源 ID 是 https://help.kusto.windows.net
Microsoft Entra租户 ID Microsoft Entra ID 是一个多租户服务,每个组织都可以创建一个名为 目录的对象,用于保存与安全相关的对象,例如用户帐户和应用程序。 Microsoft Entra ID 通常将目录称为租户。 每个租户都有一个 GUID 形式的租户 ID。 在许多情况下,组织的域名也可用于标识Microsoft Entra租户。

示例:“Contoso”组织可能具有租户 ID 12345678-a123-4567-b890-123a456b789c 和域名 contoso.com
Microsoft Entra机构 URI 用于身份验证的终结点。 Microsoft Entra目录或租户确定Microsoft Entra颁发机构 URI。 URI 是 https://login.microsoftonline.com/{tenantId},其中 {tenantId} 是租户 ID 或域名。

示例:例如 https://login.microsoftonline.com/12345678-a123-4567-b890-123a456b789c

注意

Microsoft Entra服务终结点在国家云中更改。 使用部署在国家云中的 Azure 数据资源管理器服务时,请设置相应的国家云Microsoft Entra服务终结点。

使用 MSAL 执行用户身份验证

以下代码示例演示如何使用 MSAL 获取群集的授权令牌。 授权是通过启动交互式登录 UI 的方式完成的。 appRedirectUri是身份验证成功完成后Microsoft Entra ID 重定向到的 URL。 MSAL 会从此重定向中提取授权代码。

var kustoUri = "https://<clusterName>.<region>.kusto.windows.net";

var authClient = PublicClientApplicationBuilder.Create("<appId>")
    .WithAuthority($"https://login.microsoftonline.com/<appTenant>")
    .WithRedirectUri("<appRedirectUri>")
    .Build();

var result = authClient.AcquireTokenInteractive(
    new[] { $"{kustoUri}/.default" } // Define scopes for accessing Azure Data Explorer cluster
).ExecuteAsync().Result;

var bearerToken = result.AccessToken;

var request = WebRequest.Create(new Uri(kustoUri));
request.Headers.Set(HttpRequestHeader.Authorization, string.Format(CultureInfo.InvariantCulture, "{0} {1}", "Bearer", bearerToken));

注意

  • 建议尽可能使用 Kusto 客户端库。 这些库让你能够在 Kusto 连接字符串中提供身份验证属性,从而简化了身份验证过程。
  • 使用 Kusto 客户端库时,Microsoft Entra令牌存储在用户计算机上的本地令牌缓存中,以减少提示输入凭据的次数。 缓存文件为 %APPDATA%\Kusto\userTokenCache.data,只有已登录的用户可访问它。

使用 MSAL 执行应用程序身份验证

以下代码示例演示如何使用 MSAL 获取群集的授权令牌。 在此流中,不会显示任何提示。 应用程序必须注册Microsoft Entra ID,并且必须具有应用密钥或 X509v2 证书,该证书由Microsoft Entra ID 颁发。 若要设置应用程序,请参阅预配Microsoft Entra应用程序

var kustoUri = "https://<clusterName>.<region>.kusto.windows.net";

var authClient = ConfidentialClientApplicationBuilder.Create("<appId>")
    .WithAuthority($"https://login.microsoftonline.com/<appTenant>")
    .WithClientSecret("<appKey>") // Can be replaced by .WithCertificate to authenticate with an X.509 certificate
    .Build();

var result = authClient.AcquireTokenForClient(
    new[] { $"{kustoUri}/.default" } // Define scopes for accessing Azure Data Explorer cluster
).ExecuteAsync().Result;
var bearerToken = result.AccessToken;

var request = WebRequest.Create(new Uri(kustoUri));
request.Headers.Set(HttpRequestHeader.Authorization, string.Format(CultureInfo.InvariantCulture, "{0} {1}", "Bearer", bearerToken));

注意

建议尽可能使用 Kusto 客户端库。 这些库让你能够在 Kusto 连接字符串中提供身份验证属性,从而简化了身份验证过程。

执行代理 (OBO) 身份验证

当 Web 应用程序或服务充当用户/应用程序与群集之间的中介时,适合使用代理身份验证

在此方案中,向应用程序发送任意资源的Microsoft Entra访问令牌。 然后,应用程序使用该令牌获取 Azure 数据资源管理器 资源的新Microsoft Entra访问令牌。 然后,应用程序可以代表原始Microsoft Entra访问令牌指示的主体访问群集。 此流被称为 OAuth 2.0 代理身份验证流。 它通常需要多个配置步骤和Microsoft Entra ID,在某些情况下,可能需要Microsoft Entra租户管理员的特别同意。

若要执行代理身份验证,请执行以下操作:

  1. 预配Microsoft Entra应用程序

  2. 在应用程序和群集之间建立信任关系。 为此,请按照配置委托的权限中的步骤操作。

  3. 在服务器代码中,使用 MSAL 执行令牌交换。

    var kustoUri = "https://<clusterName>.<region>.kusto.windows.net";
    
    var authClient = ConfidentialClientApplicationBuilder.Create("<appId>")
        .WithAuthority($"https://login.microsoftonline.com/<appTenant>")
        .WithClientSecret("<appKey>") // Can be replaced by .WithCertificate to authenticate with an X.509 certificate
        .Build();
    
    var result = authClient.AcquireTokenOnBehalfOf(
        new[] { $"{kustoUri}/.default" }, // Define scopes for accessing your cluster
        new UserAssertion("<userAccessToken>") // Encode the "original" token that will be used for exchange
    ).ExecuteAsync().Result;
    var accessTokenForAdx = result.AccessToken;
    
  4. 使用令牌运行查询。 例如:

    var request = WebRequest.Create(new Uri(kustoUri));
    request.Headers.Set(HttpRequestHeader.Authorization, string.Format(CultureInfo.InvariantCulture, "{0} {1}", "Bearer", accessTokenForAdx));
    

执行单页应用程序 (SPA) 身份验证

对于 SPA Web 客户端的身份验证,请使用 OAuth 授权代码流

在此方案中,将重定向应用以登录到Microsoft Entra ID。 然后,Microsoft Entra ID 重定向回具有 URI 中授权代码的应用。 然后,应用向令牌终结点发出请求以获取访问令牌。 该令牌在 24 小时内有效,在此期间,客户端可以通过以无提示方式获取令牌来重用该令牌。

Microsoft 标识平台提供了针对不同用例(例如ReactAngularJavaScript)的详细教程。

若要为 Web 客户端设置身份验证,请执行以下操作:

  1. 预配Microsoft Entra应用程序

  2. 按照采用身份验证代码流的 MSAL.js 2.0 中所述配置应用。

  3. 使用 MSAL.js 2.0 库将用户登录,并向群集进行身份验证。 Microsoft 标识平台提供了针对不同用例(例如ReactAngularJavaScript)的详细教程。

    以下示例使用 MSAL.js 库来访问 Azure 数据资源管理器。

    import * as msal from "@azure/msal-browser";
    
    const msalConfig = {
      auth: {
        clientId: "<AAD client application ID>",
        authority: "https://login.microsoftonline.com/<AAD tenant ID>",
      },
    };
    
    const msalInstance = new msal.PublicClientApplication(msalConfig);
    const myAccounts = msalInstance.getAllAccounts();
    
    // If no account is logged in, redirect the user to log in.
    if (myAccounts === undefined || myAccounts.length === 0) {
      try {
        await msalInstance.loginRedirect({
          scopes: ["https://help.kusto.windows.net/.default"],
        });
      } catch (err) {
        console.error(err);
      }
    }
    const account = myAccounts[0];
    const name = account.name;
    window.document.getElementById("main").innerHTML = `Hi ${name}!`;
    
    // Get the access token required to access the specified Azure Data Explorer cluster.
    const accessTokenRequest = {
      account,
      scopes: ["https://help.kusto.windows.net/.default"],
    };
    let acquireTokenResult = undefined;
    try {
      acquireTokenResult = await msalInstance.acquireTokenSilent(accessTokenRequest);
    } catch (error) {
      if (error instanceof InteractionRequiredAuthError) {
        await msalInstance.acquireTokenRedirect(accessTokenRequest);
      }
    }
    
    const accessToken = acquireTokenResult.accessToken;
    
    // Make requests to the specified cluster with the token in the Authorization header.
    const fetchResult = await fetch("https://help.kusto.windows.net/v2/rest/query", {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Content-Type": "application/json",
      },
      method: "POST",
      body: JSON.stringify({
        db: "Samples",
        csl: "StormEvents | count",
      }),
    });
    const jsonResult = await fetchResult.json();
    
    // The following line extracts the first cell in the result data.
    const count = jsonResult.filter((x) => x.TableKind === "PrimaryResult")[0].Rows[0][0];