
在當今的應用程式中,身份驗證是強制性的,而微軟的身份驗證庫(MSAL)是解決這一問題的有力方案。本文將向您展示在您自己的 React 程式碼中實現 MSAL 的所有細節。
在當今的數字環境中,確保使用者資料的安全和隱私至關重要。無論您是在構建 Web 應用程式、移動應用程式還是其他任何需要使用者身份驗證的軟體,Microsoft 的 React Authentication Library( MSAL-React
)都能提供一個強大的解決方案來簡化這一過程。通過 MSAL-React,開發人員可以將安全身份驗證無縫整合到他們的應用程式中,為使用者提供安全、友好的使用體驗。
在本綜合指南中,我們將一步一步地指導您使用 MSAL-React 實施身份驗證,幫助您利用微軟身份驗證平臺的強大功能來保護使用者資料並提高應用程式的可信度。無論您是經驗豐富的開發人員還是剛剛開始工作,本文都將為您提供相關知識和工具,幫助您在 React 應用程式中採用強大的身份驗證功能。
設定開發環境
構建應用程式所需的軟體和工具有:
- Node.js 和 npm:從官方網站安裝
Node.js
,其中包括 npm
。npm
用於管理依賴關係和執行指令碼。
- 複製模板: 該模板已構建了單頁前端。下面是複製的方法:
git clone <your_repository_url>
git clone <your_repository_url>
git clone <your_repository_url>
在終端中使用此命令導航到專案目錄。
cd msal-react-demo-template
cd msal-react-demo-template
cd msal-react-demo-template
導航到應用程式目錄後,安裝依賴項。
npm install
啟動應用程式。
npm start
下面是該程式使用者介面的初始外觀。

npm install --save @azure/msal-browser @azure/msal-react
npm install --save @azure/msal-browser @azure/msal-react
npm install --save @azure/msal-browser @azure/msal-react
專案結構如下:
msal-react-demo-template/
msal-react-demo-template/
|-- node_modules/
|-- public/
|-- src/
| |-- components/
|-- NavBar.jsx
|-- PageLayout.jsx
|-- ProfileData.jsx
|-- SignInButton.jsx
|-- SignOutButton.jsx
|-- WelcomeName.jsx
| |-- pages/
|-- Home.jsx
|-- Profile.jsx
| |-- styles/
|-- theme.js
| |-- App.js
| |-- index.js
|-- .gitignore
|-- LICENSE
|-- package-lock.json
|-- package.json
|-- README.md
msal-react-demo-template/
|-- node_modules/
|-- public/
|-- src/
| |-- components/
|-- NavBar.jsx
|-- PageLayout.jsx
|-- ProfileData.jsx
|-- SignInButton.jsx
|-- SignOutButton.jsx
|-- WelcomeName.jsx
| |-- pages/
|-- Home.jsx
|-- Profile.jsx
| |-- styles/
|-- theme.js
| |-- App.js
| |-- index.js
|-- .gitignore
|-- LICENSE
|-- package-lock.json
|-- package.json
|-- README.md
Azure AD 應用程式註冊
Azure Active Directory(Azure AD)是微軟基於雲的身份和訪問管理服務。它提供了一個全面的解決方案,用於管理使用者身份並確保對雲中和企業內部應用程式和資源的訪問安全。在本指南中,Azure AD 對於為應用程式新增身份驗證和授權至關重要,可確保只有授權使用者才能訪問資源。
建立 Azure AD 應用程式註冊並獲取客戶端 ID
- 訪問 https://portal.azure.com/。
- 使用 Microsoft 帳戶登入或建立一個帳戶。
- 在搜尋欄中搜尋 “App Registration”。
- 點選 “New Registration”。
- 填寫要用於應用程式的名稱。
- 選擇支援的帳戶型別。本文僅使用 Microsoft 個人賬戶。
- 對於重定向 URI,選擇 “Single-page application (SPA)”,並將 URI 設定為
http://localhost:3000/
。
- 點選 “Register”。
- 在 “Overview” 選單上,可以複製客戶端 ID。
MSAL-React 整合
在應用程式中配置 MSAL-React
,以啟用安全且使用者友好的基於 Azure AD 的身份驗證和授權。
為 MSAL 設定配置
在 index.js
檔案中,您將按照以下步驟配置將 MSAL-React
整合到 React 應用程式中。
- 匯入必要的庫:首先,從
msal-browser
中匯入 PublicClientApplication
。MSAL
(Microsoft Authentication Library,微軟身份驗證庫)是一個便於 Azure AD 身份驗證和授權的庫。
import { PublicClientApplication } from '@azure/msal-browser';
import { PublicClientApplication } from '@azure/msal-browser';
import { PublicClientApplication } from '@azure/msal-browser';
- 例項化
pubClientApp
物件並提供配置選項:通過配置基本選項建立 pubClientApp
物件。這些選項定義了應用程式與 Azure AD 的互動方式。下面是對每個選項的解釋:
clientId
:這是從 Azure AD 應用程式註冊中獲得的應用程式客戶端 ID。
許可權
authority
:授權 URL 指定了身份驗證和授權的發生位置。對於 Azure AD 消費者賬戶,請使用 “https://login.microsoftonline.com/consumers”。
redirectURI
:這是使用者身份驗證成功後將重定向到的 URI。應根據應用程式的設定進行配置。
const pubClientApp = new PublicClientApplication({
clientId: "Paste your client ID",
authority: "https://login.microsoftonline.com/consumers",
const pubClientApp = new PublicClientApplication({
auth: {
clientId: "Paste your client ID",
authority: "https://login.microsoftonline.com/consumers",
redirectUri: "/",
},
});
const pubClientApp = new PublicClientApplication({
auth: {
clientId: "Paste your client ID",
authority: "https://login.microsoftonline.com/consumers",
redirectUri: "/",
},
});
注:為確保最佳效能,必須在元件樹之外例項化 pubClientApp
物件。這樣可以避免在元件重新渲染時重新建立該物件,從而降低效率。把它放在元件外,就能保證只建立一次,並在需要時重複使用。
- 將
pubClientApp
物件作為 prop
傳遞給應用程式元件:現在,將 pubClientApp
物件提供給應用程式元件。通常的做法是將其作為 prop
傳遞給元件,這樣應用程式就能無縫地管理身份驗證和授權。
<App msalInstance={pubClientApp}/>
<App msalInstance={pubClientApp}/>
<App msalInstance={pubClientApp}/>
初始化 MSAL 提供程式
要使應用程式中的元件能夠訪問身份驗證狀態,應將它們封裝在 MsalProvider
元件中。請按照以下步驟在 App.js
檔案中進行設定:
- 首先,從
msal-react
庫中匯入 MsalProvider
元件。
import { MsalProvider } from "@azure/msal-react";
import { MsalProvider } from "@azure/msal-react";
import { MsalProvider } from "@azure/msal-react";
- 用
MsalProvider
封裝應用程式元件。提供 msalInstance
屬性並將配置好的應用程式例項傳遞給 MsalProvider
。
function App({ msalInstance }) {
<MsalProvider instance={msalInstance}>
<Grid container justifyContent="center">
function App({ msalInstance }) {
return (
<MsalProvider instance={msalInstance}>
<PageLayout>
<Grid container justifyContent="center">
<Pages />
</Grid>
</PageLayout>
</MsalProvider>
);
}
function App({ msalInstance }) {
return (
<MsalProvider instance={msalInstance}>
<PageLayout>
<Grid container justifyContent="center">
<Pages />
</Grid>
</PageLayout>
</MsalProvider>
);
}
通過用 MsalProvider
封裝元件,應用程式可以訪問 msal-react
上下文。該上下文提供了對身份驗證相關功能的訪問,使在 React 應用程式中實施安全身份驗證和授權變得更容易。
建立登入元件
要為應用程式建立登入元件,請按照 SignInButton.jsx
檔案中的以下步驟操作:
- 首先匯入
useMsal
鉤子以訪問 MSAL
例項。
import { useMsal } from '@azure/msal-react';
import { useMsal } from '@azure/msal-react';
import { useMsal } from '@azure/msal-react';
- 利用
useMsal
鉤子訪問 MSAL instance
。使用鉤子建立名為 instance
的變數,從而訪問先前配置的 MSAL instance
。
const { instance } = useMsal();
const { instance } = useMsal();
const { instance } = useMsal();
- 使用
instance.loginPopup()
方法定義 “handleLogin” 函式。該函式通過彈出視窗提示使用者使用使用者名稱和密碼登入
const handleLogin = () => {
const handleLogin = () => {
instance.loginPopup();
};
const handleLogin = () => {
instance.loginPopup();
};
- 在使用者首次登入時,通過指定
scopes
等選項來請求許可權,從而定製登入體驗。
const handleLogin = () => {
const handleLogin = () => {
instance.loginPopup({
scopes: ["user.read"],
});
};
const handleLogin = () => {
instance.loginPopup({
scopes: ["user.read"],
});
};
- 為元件中的按鈕新增呼叫
handleLogin
函式的 onClick
屬性。
<Button color="inherit" onClick={handleLogin}>
<Button color="inherit" onClick={handleLogin}>
Sign in
</Button>
<Button color="inherit" onClick={handleLogin}>
Sign in
</Button>
以下是 SignInButton.jsx
檔案,供參考:
import Button from "@mui/material/Button"; // Importing a button component from the Material-UI library.
import { useMsal } from "@azure/msal-react"; // Importing the useMsal hook from Azure MSAL for handling authentication.
export const SignInButton = () => {
const { instance } = useMsal(); // Access the instance object from the useMsal hook.
const handleLogin = () => {
scopes: ["user.read"], // Configuring the loginPopup with the "user.read" scope.
<Button color="inherit" onClick={handleLogin}>
Sign in {/* Render a button with the label "Sign in" and bind the handleLogin function to the click event. */}
import Button from "@mui/material/Button"; // Importing a button component from the Material-UI library.
import { useMsal } from "@azure/msal-react"; // Importing the useMsal hook from Azure MSAL for handling authentication.
export const SignInButton = () => {
const { instance } = useMsal(); // Access the instance object from the useMsal hook.
const handleLogin = () => {
instance.loginPopup({
scopes: ["user.read"], // Configuring the loginPopup with the "user.read" scope.
});
};
return (
<Button color="inherit" onClick={handleLogin}>
Sign in {/* Render a button with the label "Sign in" and bind the handleLogin function to the click event. */}
</Button>
);
};
import Button from "@mui/material/Button"; // Importing a button component from the Material-UI library.
import { useMsal } from "@azure/msal-react"; // Importing the useMsal hook from Azure MSAL for handling authentication.
export const SignInButton = () => {
const { instance } = useMsal(); // Access the instance object from the useMsal hook.
const handleLogin = () => {
instance.loginPopup({
scopes: ["user.read"], // Configuring the loginPopup with the "user.read" scope.
});
};
return (
<Button color="inherit" onClick={handleLogin}>
Sign in {/* Render a button with the label "Sign in" and bind the handleLogin function to the click event. */}
</Button>
);
};
建立簽出元件
建立簽出元件的方法與建立簽入元件類似。請在 SignOutButton.jsx
檔案中按照以下步驟建立簽出元件:
- 從
msal-react
中匯入 useMsal
鉤子,以訪問用於處理簽出的 MSAL instance
。
import { useMsal } from '@azure/msal-react';
import { useMsal } from '@azure/msal-react';
import { useMsal } from '@azure/msal-react';
- 利用
useMsal
鉤子訪問 MSAL instance
。使用 useMsal
鉤子建立一個名為 instance
的變數。這樣就可以訪問為應用程式配置的 MSAL instance
。
const { instance } = useMsal();
const { instance } = useMsal();
const { instance } = useMsal();
- 定義
handleLogout
函式,該函式使用 instance.logoutPopup()
方法。該函式會觸發一個用於登出使用者的彈出視窗,並在登出後將使用者重定向到主頁。
const handleLogout = () => {
const handleLogout = () => {
instance.logoutPopup();
};
const handleLogout = () => {
instance.logoutPopup();
};
- 將
handleLogout
功能整合到元件中按鈕的 onClick
屬性中。
<Button color="inherit" onClick={handleLogout}>
<Button color="inherit" onClick={handleLogout}>
Sign out
</Button>;
<Button color="inherit" onClick={handleLogout}>
Sign out
</Button>;
下面是 SignOutButton.jsx
檔案,供參考:
import Button from "@mui/material/Button"; // Importing a button component from the Material-UI library.
import { useMsal } from "@azure/msal-react"; // Importing the useMsal hook from Azure MSAL for handling authentication.
export const SignOutButton = () => {
const { instance } = useMsal(); // Access the instance object from the useMsal hook.
const handleLogout = () => {
instance.logoutPopup(); // Call the logoutPopup method from the instance object to initiate the sign-out process.
<Button color="inherit" onClick={handleLogout}>
Sign out {/* Render a button with the label "Sign out" and bind the handleLogout function to the click event. */}
import Button from "@mui/material/Button"; // Importing a button component from the Material-UI library.
import { useMsal } from "@azure/msal-react"; // Importing the useMsal hook from Azure MSAL for handling authentication.
export const SignOutButton = () => {
const { instance } = useMsal(); // Access the instance object from the useMsal hook.
const handleLogout = () => {
instance.logoutPopup(); // Call the logoutPopup method from the instance object to initiate the sign-out process.
};
return (
<Button color="inherit" onClick={handleLogout}>
Sign out {/* Render a button with the label "Sign out" and bind the handleLogout function to the click event. */}
</Button>
);
};
import Button from "@mui/material/Button"; // Importing a button component from the Material-UI library.
import { useMsal } from "@azure/msal-react"; // Importing the useMsal hook from Azure MSAL for handling authentication.
export const SignOutButton = () => {
const { instance } = useMsal(); // Access the instance object from the useMsal hook.
const handleLogout = () => {
instance.logoutPopup(); // Call the logoutPopup method from the instance object to initiate the sign-out process.
};
return (
<Button color="inherit" onClick={handleLogout}>
Sign out {/* Render a button with the label "Sign out" and bind the handleLogout function to the click event. */}
</Button>
);
};
根據身份驗證狀態有條件地渲染 UI 元素
要根據使用者的身份驗證狀態有條件地在應用程式中呈現 UI 元素,請在 NavBar.jsx
和 Home.jsx
檔案中按照以下步驟操作。
從 msal-react
匯入 useIsAuthenticated
鉤子。此鉤子允許根據使用者的身份驗證狀態有條件地呈現元素。
import { useIsAuthenticated } from "@azure/msal-react";
import { useIsAuthenticated } from "@azure/msal-react";
import { useIsAuthenticated } from "@azure/msal-react";
根據使用者的身份驗證狀態,有條件地在元件中呈現 WelcomeName
元素。
// Conditional rendering: Display the WelcomeName component only if isAuthenticated is true.
isAuthenticated ? <WelcomeName /> : null;
// Conditional rendering: Display the WelcomeName component only if isAuthenticated is true.
{
isAuthenticated ? <WelcomeName /> : null;
}
// Conditional rendering: Display the WelcomeName component only if isAuthenticated is true.
{
isAuthenticated ? <WelcomeName /> : null;
}
根據使用者的身份驗證狀態有條件地渲染 SignInButton
和 SignOutButton
元素。如果已通過身份驗證,則渲染 SignOutButton
,如果未通過身份驗證,則渲染 SignInButton
。
// Display the SignOutButton if isAuthenticated is true, otherwise display the SignInButton.
isAuthenticated ? <SignOutButton /> : <SignInButton />;
// Display the SignOutButton if isAuthenticated is true, otherwise display the SignInButton.
{
isAuthenticated ? <SignOutButton /> : <SignInButton />;
}
// Display the SignOutButton if isAuthenticated is true, otherwise display the SignInButton.
{
isAuthenticated ? <SignOutButton /> : <SignInButton />;
}
利用 msal-react
提供的 AuthenticatedTemplate
和 UnauthenticatedTemplate
元件實現條件文字呈現。從 msal-react
匯入 AuthenticatedTemplate
和 UnauthenticatedTemplate
。
import { AuthenticatedTemplate, UnauthenticatedTemplate } from "@azure/msal-react"
import { AuthenticatedTemplate, UnauthenticatedTemplate } from "@azure/msal-react"
import { AuthenticatedTemplate, UnauthenticatedTemplate } from "@azure/msal-react"
在 AuthenticatedTemplate
中包圍包含文字的 Typography
元素,這些文字將在使用者登入時可見。
<Typography variant="h6">
You are signed-in. Select profile to call Microsoft Graph.
</AuthenticatedTemplate>;
<AuthenticatedTemplate>
<Typography variant="h6">
You are signed-in. Select profile to call Microsoft Graph.
</Typography>
</AuthenticatedTemplate>;
<AuthenticatedTemplate>
<Typography variant="h6">
You are signed-in. Select profile to call Microsoft Graph.
</Typography>
</AuthenticatedTemplate>;
在 UnauthenticatedTemplate
中封裝使用者簽出時應可見的 Typography
元素。
<UnauthenticatedTemplate>
<Typography variant="h6">
Please sign in to see your profile information.
</UnauthenticatedTemplate>;
<UnauthenticatedTemplate>
<Typography variant="h6">
Please sign in to see your profile information.
</Typography>
</UnauthenticatedTemplate>;
<UnauthenticatedTemplate>
<Typography variant="h6">
Please sign in to see your profile information.
</Typography>
</UnauthenticatedTemplate>;
下面是這款應用程式的預覽,它可以根據你的登入狀態有選擇性地顯示特定資訊。

使用 Tokens
我們將深入探討獲取訪問 tokens 和發出經過驗證的 API 請求的實際步驟。訪問 tokens 是安全訪問外部資源的關鍵,我們將探討如何在應用程式中有效使用它們。
獲取訪問 tokens
要獲取訪問 tokens 以發出經過驗證的 API 請求,請按照 Profile.jsx
檔案中的以下步驟操作:
- 在
Profile.jsx
檔案開頭匯入必要的依賴項。這些依賴項是處理身份驗證和獲取訪問 tokens 所必需的。
import { useMsalAuthentication } from "@azure/msal-react";
import { InteractionType } from "@azure/msal-browser";
import { useEffect, useState } from "react";
import { useMsalAuthentication } from "@azure/msal-react";
import { InteractionType } from "@azure/msal-browser";
import { useEffect, useState } from "react";
import { useMsalAuthentication } from "@azure/msal-react";
import { InteractionType } from "@azure/msal-browser";
import { useEffect, useState } from "react";
- 使用
useState
鉤子建立名為 displayData
的狀態變數。該狀態變數將儲存從已驗證的應用程式介面獲取的資料
const [displayData, setDisplayData] = useState(null);
const [displayData, setDisplayData] = useState(null);
const [displayData, setDisplayData] = useState(null);
- 利用
useMsalAuthentication
鉤子獲取訪問 tokens。該鉤子需要兩個引數:interaction type
和指定請求 scopes
的物件。
const { result, error } = useMsalAuthentication(InteractionType.Redirect, {
const { result, error } = useMsalAuthentication(InteractionType.Redirect, {
scopes: ["user.read"],
});
const { result, error } = useMsalAuthentication(InteractionType.Redirect, {
scopes: ["user.read"],
});
要處理訪問 token 並執行相關操作,請使用 useEffect
鉤子。當元件掛載時,應執行此效果。在此效果中,您可以執行一系列檢查:
- 檢查
displayData
是否存在,以防止在資料已經可用的情況下不必要地重新執行效果。
- 檢查是否存在任何身份驗證錯誤,並將其記錄到控制檯以進行錯誤處理。
- 檢查
result
是否存在,然後提取訪問 token。
const accessToken = result.accessToken;
}, [displayData, error, result]);
useEffect(() => {
if (!displayData) {
return;
}
if (error) {
console.log(error);
return;
}
if (result) {
const accessToken = result.accessToken;
}
}, [displayData, error, result]);
useEffect(() => {
if (!displayData) {
return;
}
if (error) {
console.log(error);
return;
}
if (result) {
const accessToken = result.accessToken;
}
}, [displayData, error, result]);
執行通過身份驗證的 API 請求
要在 React 應用程式中發出通過身份驗證的 API 請求並處理響應,請按照以下步驟操作:
在 src 資料夾中建立名為 Fetch.js
的新檔案,以封裝用於發出 API 請求的函式。
定義一個名為 retrieveData
的函式,將 endpoint
和 access token
作為引數。該函式將處理 API 請求。
export const retrieveData = (endpoint, accessToken) => {};
export const retrieveData = (endpoint, accessToken) => {};
export const retrieveData = (endpoint, accessToken) => {};
在 retrieveData
函式中,建立 Headers
物件,並用訪問 token(bearer
token)設定授權標題。
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
建立一個包含 HTTP method
和 headers
的 options
物件。
const options = {
method: "GET",
headers: headers,
};
const options = {
method: "GET",
headers: headers,
};
使用 fetch
函式發出 API 請求。使用 .then()
處理響應,並使用 .catch()
捕捉任何錯誤。
return fetch(endpoint, options)
.then((response) => response.json())
.catch((error) => console.log(error));
return fetch(endpoint, options)
.then((response) => response.json())
.catch((error) => console.log(error));
return fetch(endpoint, options)
.then((response) => response.json())
.catch((error) => console.log(error));
下面是 Fetch.js
檔案,供參考:
export const retrieveData = (endpoint, accessToken) => {
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
return fetch(endpoint, options)
.then((response) => response.json())
.catch((error) => console.log(error));
export const retrieveData = (endpoint, accessToken) => {
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
const options = {
method: "GET",
headers: headers,
};
return fetch(endpoint, options)
.then((response) => response.json())
.catch((error) => console.log(error));
};
export const retrieveData = (endpoint, accessToken) => {
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
const options = {
method: "GET",
headers: headers,
};
return fetch(endpoint, options)
.then((response) => response.json())
.catch((error) => console.log(error));
};
從 Fetch.js
匯入 retrieveData
函式。這將為您的配置檔案元件做好準備,以便利用該功能發出經過身份驗證的 API 請求。
import { retrieveData } from "../Fetch";
import { retrieveData } from "../Fetch";
import { retrieveData } from "../Fetch";
使用 retrieveData
方法發出經過驗證的 API 請求。例如,可以將 endpoint
設定為 “https://graph.microsoft.com/v1.0/me”。
const accessToken = result.accessToken;
retrieveData("https://graph.microsoft.com/v1.0/me", accessToken)
.then((response) => setDisplayData(response))
.catch((error) => console.log(error));
if (result) {
const accessToken = result.accessToken;
retrieveData("https://graph.microsoft.com/v1.0/me", accessToken)
.then((response) => setDisplayData(response))
.catch((error) => console.log(error));
}
if (result) {
const accessToken = result.accessToken;
retrieveData("https://graph.microsoft.com/v1.0/me", accessToken)
.then((response) => setDisplayData(response))
.catch((error) => console.log(error));
}
在元件的 return
語句中,如果存在資料,則渲染資料( displayData
);否則,不顯示任何資料。
return <>{displayData ? <ProfileData displayData={displayData} /> : null}</>;
return <>{displayData ? <ProfileData displayData={displayData} /> : null}</>;
return <>{displayData ? <ProfileData displayData={displayData} /> : null}</>;
下面是 Profile.jsx
檔案,供參考:
import { ProfileData } from "../components/ProfileData"; // Importing the ProfileData component
import { useMsalAuthentication } from "@azure/msal-react"; // Importing the useMsalAuthentication hook from Azure MSAL
import { InteractionType } from "@azure/msal-browser"; // Importing the InteractionType from Azure MSAL
import { useEffect, useState } from "react"; // Importing the useEffect and useState hooks from React
import { retrieveData } from "../Fetch"; // Importing the retrieveData function from a custom module
export const Profile = () => {
const [displayData, setDisplayData] = useState(null); // Initializing a state variable displayData using useState
const { result, error } = useMsalAuthentication(InteractionType.Redirect, {
scopes: ["user.read"], // Configuring the useMsalAuthentication hook with a specified scope
return; // If displayData is already populated, do nothing
console.log(error); // If there's an error, log it to the console
const accessToken = result.accessToken; // Access the accessToken property from the result object
retrieveData("https://graph.microsoft.com/v1.0/me", accessToken) // Call the retrieveData function with the access token
.then((response) => setDisplayData(response)) // Set the displayData state with the response data
.catch((error) => console.log(error)); // Handle and log any errors
}, [displayData, error, result]); // Run this effect when displayData, error, or result changes
return <>{displayData ? <ProfileData displayData={displayData} /> : null}</>; // Conditional rendering of the ProfileData component based on the displayData state
import { ProfileData } from "../components/ProfileData"; // Importing the ProfileData component
import { useMsalAuthentication } from "@azure/msal-react"; // Importing the useMsalAuthentication hook from Azure MSAL
import { InteractionType } from "@azure/msal-browser"; // Importing the InteractionType from Azure MSAL
import { useEffect, useState } from "react"; // Importing the useEffect and useState hooks from React
import { retrieveData } from "../Fetch"; // Importing the retrieveData function from a custom module
export const Profile = () => {
const [displayData, setDisplayData] = useState(null); // Initializing a state variable displayData using useState
const { result, error } = useMsalAuthentication(InteractionType.Redirect, {
scopes: ["user.read"], // Configuring the useMsalAuthentication hook with a specified scope
});
useEffect(() => {
if (!displayData) {
return; // If displayData is already populated, do nothing
}
if (error) {
console.log(error); // If there's an error, log it to the console
return;
}
if (result) {
const accessToken = result.accessToken; // Access the accessToken property from the result object
retrieveData("https://graph.microsoft.com/v1.0/me", accessToken) // Call the retrieveData function with the access token
.then((response) => setDisplayData(response)) // Set the displayData state with the response data
.catch((error) => console.log(error)); // Handle and log any errors
}
}, [displayData, error, result]); // Run this effect when displayData, error, or result changes
return <>{displayData ? <ProfileData displayData={displayData} /> : null}</>; // Conditional rendering of the ProfileData component based on the displayData state
};
import { ProfileData } from "../components/ProfileData"; // Importing the ProfileData component
import { useMsalAuthentication } from "@azure/msal-react"; // Importing the useMsalAuthentication hook from Azure MSAL
import { InteractionType } from "@azure/msal-browser"; // Importing the InteractionType from Azure MSAL
import { useEffect, useState } from "react"; // Importing the useEffect and useState hooks from React
import { retrieveData } from "../Fetch"; // Importing the retrieveData function from a custom module
export const Profile = () => {
const [displayData, setDisplayData] = useState(null); // Initializing a state variable displayData using useState
const { result, error } = useMsalAuthentication(InteractionType.Redirect, {
scopes: ["user.read"], // Configuring the useMsalAuthentication hook with a specified scope
});
useEffect(() => {
if (!displayData) {
return; // If displayData is already populated, do nothing
}
if (error) {
console.log(error); // If there's an error, log it to the console
return;
}
if (result) {
const accessToken = result.accessToken; // Access the accessToken property from the result object
retrieveData("https://graph.microsoft.com/v1.0/me", accessToken) // Call the retrieveData function with the access token
.then((response) => setDisplayData(response)) // Set the displayData state with the response data
.catch((error) => console.log(error)); // Handle and log any errors
}
}, [displayData, error, result]); // Run this effect when displayData, error, or result changes
return <>{displayData ? <ProfileData displayData={displayData} /> : null}</>; // Conditional rendering of the ProfileData component based on the displayData state
};
下面是該應用的預覽版,展示了使用者登入時的具體細節。

顯示已登入使用者的名稱
要在使用者介面中顯示已登入使用者的姓名以增強使用者體驗,請按以下步驟操作:
匯入必要的依賴項並設定 MSAL
事件回撥以處理成功登入事件。
import { PublicClientApplication, EventType } from "@azure/msal-browser";
// Add an MSAL event callback to set the active account
pubClientApp.addEventCallback((event) => {
if (event.eventType === EventType.LOGIN_SUCCESS) {
pubClientApp.setActiveAccount(event.payload.account);
import { PublicClientApplication, EventType } from "@azure/msal-browser";
// Add an MSAL event callback to set the active account
pubClientApp.addEventCallback((event) => {
if (event.eventType === EventType.LOGIN_SUCCESS) {
console.log(event);
pubClientApp.setActiveAccount(event.payload.account);
}
});
import { PublicClientApplication, EventType } from "@azure/msal-browser";
// Add an MSAL event callback to set the active account
pubClientApp.addEventCallback((event) => {
if (event.eventType === EventType.LOGIN_SUCCESS) {
console.log(event);
pubClientApp.setActiveAccount(event.payload.account);
}
});
匯入訪問應用程式例項和管理元件狀態所需的依賴項。
import { useMsal } from "@azure/msal-react";
import { useState, useEffect } from "react";
import { useMsal } from "@azure/msal-react";
import { useState, useEffect } from "react";
import { useMsal } from "@azure/msal-react";
import { useState, useEffect } from "react";
定義狀態變數 username
,用於儲存登入使用者的使用者名稱。
const [username, setUsername] = useState('');
const [username, setUsername] = useState('');
const [username, setUsername] = useState('');
使用 useMsal
鉤子訪問之前建立的應用程式例項( instance
)。
const { instance } = useMsal();
const { instance } = useMsal();
const { instance } = useMsal();
在 useEffect
鉤子中,將 currentAccount
設定為活動賬戶,並更新 username
狀態變數。確保在依賴關係陣列中包含 instance
,以觀察變化。
const currentAccount = instance.getActiveAccount();
setUsername(currentAccount.username);
useEffect(() => {
const currentAccount = instance.getActiveAccount();
if (currentAccount) {
setUsername(currentAccount.username);
}
}, [instance]);
useEffect(() => {
const currentAccount = instance.getActiveAccount();
if (currentAccount) {
setUsername(currentAccount.username);
}
}, [instance]);
在元件的 return
語句中,使用 Typography
元件在使用者介面中顯示使用者名稱。
return <Typography variant="h6">Welcome, {username}</Typography>;
return <Typography variant="h6">Welcome, {username}</Typography>;
return <Typography variant="h6">Welcome, {username}</Typography>;
登入時顯示使用者名稱的應用程式快照:

錯誤處理
要在應用程式中使用 MSAL 啟用錯誤處理和日誌記錄功能,請按照以下步驟操作:
開啟 index.js
檔案:
- 在
pubClientApp
物件中,包含一個 cache
物件,其中包含 cacheLocation
和 storeAuthStateInCookie
等選項。這些選項有助於控制驗證工件的快取和管理方式。
cacheLocation: 'localStorage',
storeAuthStateInCookie: false,
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: false,
}
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: false,
}
- 在
pubClientApp
物件中包含一個 system
物件,併為日誌配置定義 loggerOptions
。這樣就可以指定 MSAL
處理日誌的方式。
loggerCallback: (level, message, containsPII) => {
console.log(message); // Define a callback function to handle log messages (in this case, logging to the console).
logLevel: 'Verbose' // Set the log level to 'Verbose' (providing detailed logs including debug information).
system: {
loggerOptions: {
loggerCallback: (level, message, containsPII) => {
console.log(message); // Define a callback function to handle log messages (in this case, logging to the console).
},
logLevel: 'Verbose' // Set the log level to 'Verbose' (providing detailed logs including debug information).
}
}
system: {
loggerOptions: {
loggerCallback: (level, message, containsPII) => {
console.log(message); // Define a callback function to handle log messages (in this case, logging to the console).
},
logLevel: 'Verbose' // Set the log level to 'Verbose' (providing detailed logs including debug information).
}
}
有了這些配置, MSAL
就會在控制檯中記錄互動、錯誤和其他資訊。您可以使用這些資訊來除錯和監控身份驗證過程。
請注意,此設定可幫助您除錯和監控與身份驗證相關的活動,並排除使用者與 Azure AD 互動過程中可能出現的任何問題。
記錄互動的瀏覽器控制檯預覽。

處理身份驗證錯誤
要在 MSAL 應用程式中處理身份驗證錯誤和索賠挑戰,請按照以下步驟操作:
在 auth
物件中新增 clientCapabilities
選項。該選項宣告應用程式能夠處理索賠挑戰。
clientId: "5d804fed-8b0e-4c9b-b949-6020d4945ead",
authority: "https://login.microsoftonline.com/consumers",
redirectUri: "http://localhost:3000/",
clientCapabilities: ['CP1']
auth: {
clientId: "5d804fed-8b0e-4c9b-b949-6020d4945ead",
authority: "https://login.microsoftonline.com/consumers",
redirectUri: "http://localhost:3000/",
clientCapabilities: ['CP1']
},
auth: {
clientId: "5d804fed-8b0e-4c9b-b949-6020d4945ead",
authority: "https://login.microsoftonline.com/consumers",
redirectUri: "http://localhost:3000/",
clientCapabilities: ['CP1']
},
- 在
Fetch.js
檔案中:新增一個名為 handleClaims
的函式,用於檢查響應的狀態程式碼。
- 如果狀態為 200(表示成功),則返回 JSON 格式的響應。
如果狀態為 401,它會檢查響應頭是否包含 “authenticated”。如果包含,則會從標頭中提取 claimsChallenge 並將其儲存到 sessionStorage 中。
const handleClaims = (response) => {
if (response.status === 200) {
return response.json(); // If the response status is 200 (OK), parse it as JSON and return the result.
} else if (response.status === 401) {
if (response.headers.get("www-authenticate")) {
const authenticateHeader = response.headers.get("www-authenticate");
const claimsChallenge = authenticateHeader
.find((entry) => entry.includes("claims=")) // Find the entry in the authenticateHeader that contains "claims=".
.split('claims="')[1] // Extract the part of the entry after 'claims="'.
.split('",')[0]; // Extract the part before the next '"'.
sessionStorage.setItem("claimsChallenge", claimsChallenge); // Store the claims challenge in session storage.
return; // Return without further processing.
throw new Error(`Error $(response.status)`); // If there's no 'www-authenticate' header, throw an error.
throw new Error(`Error $(response.status)`); // If the response status is neither 200 nor 401, throw an error.
const handleClaims = (response) => {
if (response.status === 200) {
return response.json(); // If the response status is 200 (OK), parse it as JSON and return the result.
} else if (response.status === 401) {
if (response.headers.get("www-authenticate")) {
const authenticateHeader = response.headers.get("www-authenticate");
const claimsChallenge = authenticateHeader
.split(" ")
.find((entry) => entry.includes("claims=")) // Find the entry in the authenticateHeader that contains "claims=".
.split('claims="')[1] // Extract the part of the entry after 'claims="'.
.split('",')[0]; // Extract the part before the next '"'.
sessionStorage.setItem("claimsChallenge", claimsChallenge); // Store the claims challenge in session storage.
return; // Return without further processing.
}
throw new Error(`Error $(response.status)`); // If there's no 'www-authenticate' header, throw an error.
} else {
throw new Error(`Error $(response.status)`); // If the response status is neither 200 nor 401, throw an error.
}
};
const handleClaims = (response) => {
if (response.status === 200) {
return response.json(); // If the response status is 200 (OK), parse it as JSON and return the result.
} else if (response.status === 401) {
if (response.headers.get("www-authenticate")) {
const authenticateHeader = response.headers.get("www-authenticate");
const claimsChallenge = authenticateHeader
.split(" ")
.find((entry) => entry.includes("claims=")) // Find the entry in the authenticateHeader that contains "claims=".
.split('claims="')[1] // Extract the part of the entry after 'claims="'.
.split('",')[0]; // Extract the part before the next '"'.
sessionStorage.setItem("claimsChallenge", claimsChallenge); // Store the claims challenge in session storage.
return; // Return without further processing.
}
throw new Error(`Error $(response.status)`); // If there's no 'www-authenticate' header, throw an error.
} else {
throw new Error(`Error $(response.status)`); // If the response status is neither 200 nor 401, throw an error.
}
};
修改 fetch
呼叫,通過 handleClaims
函式傳遞 response
。這可確保對響應進行處理,以處理索賠質疑或其他錯誤。
return fetch(endpoint, options)
.then((response) => handleClaims(response))
.catch((error) => console.log(error));
return fetch(endpoint, options)
.then((response) => handleClaims(response))
.catch((error) => console.log(error));
return fetch(endpoint, options)
.then((response) => handleClaims(response))
.catch((error) => console.log(error));
在 useMsalAuthentication
配置中新增一個引數 claims
。該引數設定為儲存在 sessionStorage
中的 claimsChallenge
。
const { result, error } = useMsalAuthentication(InteractionType.Redirect, {
claims: sessionStorage.getItem("claimsChallenge")
? window.atob(sessionStorage.getItem("claimsChallenge"))
const { result, error } = useMsalAuthentication(InteractionType.Redirect, {
scopes: ["user.read"],
claims: sessionStorage.getItem("claimsChallenge")
? window.atob(sessionStorage.getItem("claimsChallenge"))
: undefined,
});
const { result, error } = useMsalAuthentication(InteractionType.Redirect, {
scopes: ["user.read"],
claims: sessionStorage.getItem("claimsChallenge")
? window.atob(sessionStorage.getItem("claimsChallenge"))
: undefined,
});
通過這些步驟,您可以在 MSAL
應用程式中處理身份驗證錯誤和理賠挑戰,使其更加強大,並能夠在身份驗證過程中管理自定義理賠挑戰。
這有一份關於解決 Microsoft Entra ID 問題的故障排除指南。
小結
本綜合指南提供了使用 MSAL-React
實施身份驗證的分步指南。它幫助讀者建立開發環境、配置 MSAL-React
、建立簽入和簽出元件、提出經過驗證的 API 請求,以及有效處理身份驗證錯誤。
評論留言