MSAL React 中的挂钩

MSAL React 中的钩子是一些函数,可让你在函数组件中使用 MSAL 功能以及 React 的状态和生命周期方法。 主要的钩子是 useAccountuseIsAuthenticateduseMsaluseMsalAuthentication。 本文将带你了解这些钩子的用法。

useAccount 挂钩

useAccount 钩子接受一个 accountIdentifier 参数;如果该账户已登录,则返回该账户的 AccountInfo 对象,否则返回 null。 如果未提供帐户标识符,则返回当前 活动帐户 。 你可以在 @azure/msal-browser 文档的 MSAL 中的登录 API 一节中,进一步了解所返回的 AccountInfo 对象。

const accountIdentifier = {
    localAccountId: "example-local-account-identifier",
    homeAccountId: "example-home-account-identifier"
    username: "example-username" // We do not recommend relying only on username
}

const accountInfo = useAccount(accountIdentifier);

useIsAuthenticated 挂钩

useIsAuthenticated挂钩返回一个布尔值,该值指示帐户是否已登录。 如果你需要知道某个特定账户是否已登录,它还可以可选地接受一个由你提供的 accountIdentifier 对象。

检查当前是否有任何账户已登录

以下代码片段使用 useIsAuthenticated 包中的 @azure/msal-react 挂钩。 然后,该组件根据用户是否登录有条件地呈现消息。

import React from 'react';
import { useIsAuthenticated } from "@azure/msal-react";

export function App() {
    const isAuthenticated = useIsAuthenticated();

    return (
        <React.Fragment>
            <p>Anyone can see this paragraph.</p>
            {isAuthenticated && (
                <p>At least one account is signed in!</p>
            )}
            {!isAuthenticated && (
                <p>No users are signed in!</p>
            )}
        </React.Fragment>
    );
}

确定特定用户是否已登录

以下代码片段使用 useIsAuthenticated 包中的 @azure/msal-react 挂钩来确定特定用户是否已登录。

import React from 'react';
import { useIsAuthenticated } from "@azure/msal-react";

export function App() {
    const accountIdentifiers = {
        localAccountId: "example-local-account-identifier",
        homeAccountId: "example-home-account-identifier",
        username: "example-username"
    }

    const isAuthenticated = useIsAuthenticated(accountIdentifiers);

    return (
        <React.Fragment>
            <p>Anyone can see this paragraph.</p>
            {isAuthenticated && (
                <p>User with specified localAccountId is signed in!</p>
            )}
            {!isAuthenticated && (
                <p>User with specified localAccountId is not signed in!</p>
            )}
        </React.Fragment>
    );
}

useMsal 挂钩

useMsal挂钩返回上下文。 如果需要访问 PublicClientApplication 实例、当前已登录的帐户列表,或者是否需要知道登录名或其他交互当前是否正在进行,则可以使用此功能。

注意:由 useMsal 返回的 accounts 值仅会在添加或删除帐户时更新,而不会在声明更新时更新。 如果需要访问当前用户的更新声明,请改用 useAccount 挂钩或调用 acquireTokenSilent

import { useState, useEffect } from "react";
import { useMsal } from "@azure/msal-react";
import { InteractionStatus } from "@azure/msal-browser";

const { instance, accounts, inProgress } = useMsal();
const [loading, setLoading] = useState(false);
const [apiData, setApiData] = useState(null);

useEffect(() => {
    if (!loading && inProgress === InteractionStatus.None && accounts.length > 0) {
        if (apiData) {
            // Skip data refresh if already set - adjust logic for your specific use case
            return;
        }

        const tokenRequest = {
            account: accounts[0], // This is an example - Select account based on your app's requirements
            scopes: ["User.Read"]
        }

        // Acquire an access token
        instance.acquireTokenSilent(tokenRequest).then((response) => {
            // Call your API with the access token and return the data you need to save in state
            callApi(response.accessToken).then((data) => {
                setApiData(data);
                setLoading(false);
            });
        }).catch(async (e) => {
            // Catch interaction_required errors and call interactive method to resolve
            if (e instanceof InteractionRequiredAuthError) {
                await instance.acquireTokenRedirect(tokenRequest);
            }

            throw e;
        });
    }
}, [inProgress, accounts, instance, loading, apiData]);

if (loading || inProgress === InteractionStatus.Login) {
    // Render loading component
} else if (apiData) {
    // Render content that depends on data from your API
}

useMsalAuthentication 挂钩

useMsalAuthentication如果用户尚未登录,则挂钩将启动登录,否则它将尝试获取令牌。

输入参数

可以向 useMsalAuthentication 挂钩提供几个不同的输入参数:

  • interactionType - (None、Popup、Redirect 或 Silent)指定在需要交互时如何获取令牌或登录名(请注意,静默选项有下面介绍的一些额外注意事项)。
  • 请求对象 - (可选)指定登录或获取令牌调用要使用的其他参数
  • accountIdentifiers - 用于告知该挂钩应为哪个用户登录或获取令牌的对象

返回值属性

  • result - 上次成功登录或获取令牌的结果。 请注意,此钩子仅会自动尝试登录或获取令牌一次。 应用程序负责在需要时调用 loginacquireToken 函数来更新此值。
  • error - 如果在登录或令牌获取期间发生错误,此属性将包含有关错误的信息。 可以使用此挂钩返回的 loginacquireToken 函数重试。 在下一次成功登录或令牌获取时,将清除该 error 属性。
  • login - 可用于重试失败登录的函数。 resulterror属性将会更新。
  • acquireToken - 在调用受保护的 API 之前,可用于获取新的访问令牌的函数。 resulterror 属性将会被更新。

传递“静默”交互类型将调用 ssoSilent,该方法会尝试打开一个隐藏的 iframe,并复用与 Microsoft Entra ID 的现有会话。 这不适用于阻止第三方 Cookie(如 Safari)的浏览器。 此外,使用“无提示”类型时需要请求对象。 如果已有用户的登录信息,则可以传递 loginHintsid 可选参数以登录特定帐户。 注意:还有其他 注意事项 - 使用 ssoSilent 时不提供有关用户会话的任何信息。

ssoSilent 示例

如果使用静默模式,应捕获任何错误,并尝试以交互方式登录作为备用方案。

import React, { useEffect } from 'react';

import { AuthenticatedTemplate, UnauthenticatedTemplate, useMsal, useMsalAuthentication } from "@azure/msal-react";
import { InteractionType, InteractionRequiredAuthError } from '@azure/msal-browser';

function App() {
    const request = {
        loginHint: "name@example.com",
        scopes: ["User.Read"]
    }
    const { login, result, error } = useMsalAuthentication(InteractionType.Silent, request);

    useEffect(() => {
        if (error instanceof InteractionRequiredAuthError) {
            login(InteractionType.Popup, request);
        }
    }, [error]);

    const { accounts } = useMsal();

    return (
        <React.Fragment>
            <p>Anyone can see this paragraph.</p>
            <AuthenticatedTemplate>
                <p>Signed in as: {accounts[0]?.username}</p>
            </AuthenticatedTemplate>
            <UnauthenticatedTemplate>
                <p>No users are signed in!</p>
            </UnauthenticatedTemplate>
        </React.Fragment>
    );
}

export default App;

特定用户示例

如果要确保特定用户已登录,请提供一个 accountIdentifiers 对象。

import React from 'react';
import { useMsalAuthentication } from "@azure/msal-react";
import { InteractionType } from '@azure/msal-browser';

export function App() {
    const accountIdentifiers = {
        username: "example-username"
    }
    const request = {
        loginHint: "example-username",
        scopes: ["User.Read"]
    }
    const { login, result, error } = useMsalAuthentication(InteractionType.Popup, request, accountIdentifiers);

    return (
        <React.Fragment>
            <p>Anyone can see this paragraph.</p>
            <AuthenticatedTemplate username="example-username">
                <p>Example user is signed in!</p>
            </AuthenticatedTemplate>
            <UnauthenticatedTemplate username="example-username">
                <p>Example user is not signed in!</p>
            </UnauthenticatedTemplate>
        </React.Fragment>
    );
}

另见

您可以在 MSAL Browser 中找到 PublicClientApplication 提供的 API 文档: