练习 - 将 Next.js Web 应用与 Azure AD 集成
本练习将演练如何配置与 Microsoft Entra ID 集成的、基于 Next.js 的简单应用程序。
通过学习本练习,你将能够:
- 注册 Microsoft Entra 应用程序。
- 实现一个 Microsoft Entra 集成的基于 Next.js 的简单应用程序。
- 验证基于 Next.js 的应用程序的 Microsoft Entra 集成。
先决条件
若要进行此练习,你需要:
- Azure 订阅。
- Microsoft 帐户或 Microsoft Entra 帐户,该帐户在 Azure 订阅关联的 Microsoft Entra 租户中具有全局管理员角色并在 Azure 订阅中具有所有者或参与者角色。
- 已经完成本模块的第一个和第二个练习。
- 一台已安装或可以安装 Node.js 和 Git 的计算机。
注意
有关安装 Node.js 的信息,请参阅 Node.js 下载。 有关 Git 的信息,请参阅 Git 下载。 在开始本练习前安装这两个工具。
使用 Microsoft Entra ID 注册应用程序
若要实现使用 Microsoft Entra 身份验证访问 Azure Database for PostgreSQL 数据库的基于 Next.js 的示例应用程序,必须先创建 Microsoft Entra 应用程序对象和相应的安全主体。 这将允许基于 Next.js 的应用程序在访问数据库对象时模拟 Microsoft Entra 用户。
如果需要,请启动 Web 浏览器,导航到 Azure 门户并登录,以访问要在本模块中使用的 Azure 订阅。
使用“搜索资源、服务和文档”文本框搜索“Microsoft Entra ID”,然后在结果列表中,选择“Microsoft Entra ID”。
在 Microsoft Entra ID 窗格上,在垂直菜单的“管理”部分中选择“应用注册”。
在“应用注册”边栏选项卡上,选择“+ 新建注册”。
在“注册应用程序”边栏选项卡上的“名称”文本框中,输入 cna-nextjs-app。
在“支持的帐户类型”部分中,确保选中“仅此组织目录中的帐户(仅默认目录 - 单一租户)”选项。 在“重定向 URI (可选)”部分中,将“单页应用程序(SPA)”条目设置为 http://localhost:3000,然后选择“注册”。
注意
此时,可以选择为 Microsoft Entra 注册应用程序配置多租户支持。 但是,对这种方法的详细介绍超出了本模块的范围。
注意
部署应用程序后,需要修改“重定向 URI (可选)”值以反映其实际 URL。
在 cna-nextjs-app 边栏选项卡上,查看生成的设置,并记录“应用程序(客户端) ID”和“目录(租户) ID”属性的值。
在 cna-nextjs-app 边栏选项卡上,在垂直菜单的“管理”部分中选择“API 权限”。
在“cna-nextjs-app | API 权限”边栏选项卡上,选择“+ 添加权限”,在“请求 API 权限”边栏选项卡上,选择“我的组织使用的 API”选项卡,在搜索文本框中输入“Azure OSSRDBMS 数据库”,然后在结果列表中选择“Azure OSSRDBMS 数据库”。
在“请求 API 权限”边栏选项卡上,选择“委托的权限”,选中“user_impersonation”复选框,然后选择“添加权限”。
返回“cna-nextjs-app | API 权限”边栏选项卡,选择“为默认目录授予管理员许可”,并在提示确认时选择“是”。
在“cna-nextjs-app | API 权限”边栏选项卡上,验证是否已授予权限。
实现一个 Microsoft Entra 集成的基于 Next.js 的简单应用程序
在 Microsoft Entra 租户中注册应用程序后,现在可以继续执行其实现。 为了简化任务,你将克隆一个包含示例 Next.js 代码的 GitHub 存储库,并对其进行自定义,以与 Microsoft Entra 租户集成。
在本地计算机上,启动 Node.js 命令提示符。
注意
确保在计算机上使用本地安装的 Node.js 运行此提示符。
在 Node.js 命令提示符下运行以下命令,以克隆包含将在本练习中使用的示例 Next.js 应用程序代码的 GitHub 存储库:
git clone https://github.com/MicrosoftDocs/mslearn-cloud-native-apps.git
运行以下命令,切换到托管 GitHub 存储库克隆的目录:
cd ./mslearn-cloud-native-apps/m06u07
使用首选文本编辑器查看 ./src/App.jsx 文件的内容,该文件可从 Microsoft Entra 检索单页应用程序的访问令牌:
./src/App.jsx 文件包含以下内容:
import React, { useState } from "react"; import { AuthenticatedTemplate, UnauthenticatedTemplate, useMsal } from "@azure/msal-react"; import { loginRequest } from "./authConfig"; import { PageLayout } from "./components/PageLayout"; import { ProfileData } from "./components/ProfileData"; import { callMsGraph } from "./graph"; import Button from "react-bootstrap/Button"; import "./styles/App.css"; var accessToken = ''; /** * Renders information about the signed-in user or a button to retrieve data about the user */ const ProfileContent = () => { const { instance, accounts } = useMsal(); const [graphData, setGraphData] = useState(null); function RequestProfileData() { // Silently acquires an access token which is then attached to a request for MS Graph data instance.acquireTokenSilent({ ...loginRequest, account: accounts[0] }).then((response) => { accessToken = response.accessToken; callMsGraph(response.accessToken).then(response => setGraphData(response)); }); } return ( <> <h5 className="card-title">Welcome {accounts[0].name}</h5> {graphData ? <ProfileData graphData={graphData} /> : <Button variant="secondary" onClick={RequestProfileData}>Request Profile Information</Button> } <p>{accessToken}</p> </> ); }; /** * If a user is authenticated the ProfileContent component above is rendered. Otherwise, a message indicating a user is not authenticated is rendered. */ const MainContent = () => { return ( <div className="App"> <AuthenticatedTemplate> <ProfileContent /> </AuthenticatedTemplate> <UnauthenticatedTemplate> <h5 className="card-title">Please sign-in to review your profile information.</h5> </UnauthenticatedTemplate> </div> ); }; export default function App() { return ( <PageLayout> <MainContent /> </PageLayout> ); }
使用首选文本编辑器查看 ./src/authConfig.js 文件的内容,该文件存储了标识本练习上一个任务中注册的目标 Microsoft Entra 应用程序所需的信息。
./src/authConfig.js 文件包含以下内容:
/* * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ import { LogLevel } from "@azure/msal-browser"; /** * Configuration object to be passed to MSAL instance on creation. * For a full list of MSAL.js configuration parameters, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/configuration.md */ export const msalConfig = { auth: { clientId: "<client_ID>", authority: "https://login.microsoftonline.com/<tenant_ID>", redirectUri: "http://localhost:3000" }, cache: { cacheLocation: "sessionStorage", // This configures where your cache will be stored storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge }, system: { loggerOptions: { loggerCallback: (level, message, containsPii) => { if (containsPii) { return; } switch (level) { case LogLevel.Error: console.error(message); return; case LogLevel.Info: console.info(message); return; case LogLevel.Verbose: console.debug(message); return; case LogLevel.Warning: console.warn(message); return; } } } } }; /** * Scopes you add here will be prompted for user consent during sign-in. * By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login request. * For more information about OIDC scopes, visit: * https://learn.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes */ export const loginRequest = { scopes: ["User.Read"] }; /** * Add here the scopes to request when obtaining an access token for MS Graph API. For more information, review: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/resources-and-scopes.md */ export const graphConfig = { graphMeEndpoint: "https://graph.microsoft.com/v1.0/me" };
在显示 ./src/authConfig.js 文件内容的文本编辑器中,将
<client_ID>
和<tenant_ID>
占位符替换为其各自的值,即,在本练习的上一个任务中标识的值。在显示 ./src/authConfig.js 文件内容的文本编辑器中,将条目
scopes: ["User.Read"]
替换为scopes: ["User.Read","https://ossrdbms-aad.database.windows.net/user_impersonation"]
。保存更改并关闭文件。
验证基于 Next.js 的应用程序的 Microsoft Entra 集成
你已准备好验证应用的 Microsoft Entra 集成。 你可以将其容器化,但为简单起见,你将首先在本地计算机上的 Node.js 开发环境中运行它。 这将提供一种快速验证其功能的方法,并确保将其容器化是一个可行的选择。
在 Node.js 命令提示符下,运行以下命令安装示例 Next.js 应用程序的依赖项包:
npm install
注意
等待安装过程完成。
在 Node.js 命令提示符下,运行以下命令生成 Next.js 应用程序:
npm run-script build
注意
等待生成过程完成。
在 Node.js 命令提示符下,运行以下命令启动 Next.js 应用程序:
npm run-script start
注意
这将自动打开一个浏览器窗口,显示“欢迎使用适用于 JavaScript 的 Microsoft 身份验证库 - React 快速入门”页面。
关闭显示“欢迎使用适用于 JavaScript 的 Microsoft 身份验证库 - React 快速入门”页面的 Web 浏览器窗口,在 Incognito/InPrivate 模式下启动另一个 Web 浏览器窗口,然后导航到 http://localhost:3000 URL。
在“欢迎使用适用于 Javascript 的 Microsoft 身份验证库 - React 快速入门”页面上,选择“登录”,然后在展开菜单中选择“使用弹出窗口登录”。
当系统提示登录时,使用 adatumuser1 userPrincipalName 及其密码进行身份验证。
注意
你在本模块的第一个练习中创建了此用户帐户。
在“欢迎使用适用于 JavaScript 的 Microsoft 身份验证库 - React 快速入门”页面上,选择“请求配置文件信息”。
注意
验证输出是否包含电子邮件、ID 和 adatumuser1 Microsoft Entra 用户帐户的访问令牌。
在同一 Web 浏览器窗口中打开另一个浏览器选项卡,然后导航到上一个练习中部署的 Web 应用程序。
注意
该 URL 应采用以下格式:
https://<webapp_name>.azurewebsites.net/auth
注意
验证生成的网页是否显示第一个租户的清单数据。
注意
如果初始尝试失败,请重试。
在 Incognito/InPrivate 模式下关闭 Web 浏览器窗口。
注意
现在,将重复与 contosouser1 相同的步骤序列,并验证是否也可以访问清单数据并显示对应于第二个租户的记录集。
在 Incognito/InPrivate 模式下启动另一个 Web 浏览器窗口,然后导航到 http://localhost:3000 URL。
在“欢迎使用适用于 Javascript 的 Microsoft 身份验证库 - React 快速入门”页面上,选择“登录”,然后在展开菜单中选择“使用弹出窗口登录”。
当系统提示登录时,使用 contosouser1 userPrincipalName 及其密码进行身份验证。
注意
你在本模块的第一个练习中创建了此用户帐户。
注意
如果出现提示,请接受访问请求并更改 contosouser1 帐户的密码。
在“欢迎使用适用于 JavaScript 的 Microsoft 身份验证库 - React 快速入门”页面上,选择“请求配置文件信息”。
注意
验证输出是否包含电子邮件、ID 和 contosouser1 Microsoft Entra 用户帐户的访问令牌。
在同一 Web 浏览器窗口中打开另一个浏览器选项卡,然后导航到上一个练习中部署的 Web 应用程序。
注意
验证生成的网页是否显示第二个租户的清单数据。
结果
祝贺你! 你已完成本模块的第三个练习。 在本练习中,你实现了一个 AD 集成的基于 Next.js 的简单应用程序并验证了其功能。
清理资源
为避免因使用 Azure 资源而产生不必要的费用,你应该删除本模块上一个练习中创建的 postgresql-db-RG 和 cna-aadexpress-RG 资源组。 为此,请在 Azure 门户中导航到每个资源组的边栏选项卡,然后选择工具栏中的“删除资源组”条目。 在“键入资源组名称”文本框中,输入资源组的名称,然后选择“删除”。