MSAL React 支持函数组件和类组件。 本文提供有关将 MSAL React 与类组件配合使用的指导,使你能够在类组件中初始化、保护和访问 MSAL React 上下文。
需要注意的是,你无法在类组件内部使用 @azure/msal-react 挂钩。 如果需要访问类组件内的身份验证状态,则需要直接使用 @azure/msal-browser 来获取类似的功能。
先决条件
初始 化
使用 MSAL React 的类组件初始化与函数组件非常相似。 与使用函数组件时类似,你需要在需要访问身份验证状态的组件树顶层放置一个 MsalProvider 组件。
在以下代码片段中,该 MsalProvider 组件用于包装整个应用程序,使 MSAL 实例可供所有子组件使用。 这使子组件能够使用 MSAL 进行用户身份验证、获取令牌和调用受保护的 API。
import React from "react";
import { MsalProvider } from "@azure/msal-react";
import { PublicClientApplication } from "@azure/msal-browser";
const pca = new PublicClientApplication(config);
class App extends React.Component {
render() {
return (
<MsalProvider instance={pca}>
<YourAppComponents>
</ MsalProvider>
);
}
}
保护组件
在 MSAL React 中,可以保护组件,然后根据用户的身份验证状态有条件地呈现。 这与使用函数组件的工作方式类似。 主要示例包括:
-
AuthenticatedTemplate- 仅当用户已通过身份验证时,此组件才会渲染其子元素。 如果未对用户进行身份验证,则不会呈现任何内容。 -
UnauthenticatedTemplate- 仅当用户未通过身份验证时,此组件才会渲染其子元素。 如果用户已经过身份验证,则不会呈现任何内容。 -
MsalAuthenticationTemplate- 此组件会先尝试对用户进行身份验证,然后再渲染其子组件。 可以将交互类型(重定向或弹出窗口)指定为属性。如果未对用户进行身份验证,它将启动身份验证过程。
以下代码片段演示如何使用AuthenticatedTemplate和UnauthenticatedTemplateMsalAuthenticationTemplate保护 React 组件。 请注意 MSAL Provider 是如何包裹子组件的。
import React from "react";
import { MsalProvider, AuthenticatedTemplate, UnauthenticatedTemplate, MsalAuthenticationTemplate } from "@azure/msal-react";
import { PublicClientApplication, InteractionType } from "@azure/msal-browser";
const pca = new PublicClientApplication(config);
class App extends React.Component {
render() {
return (
<MsalProvider instance={pca}>
<AuthenticatedTemplate>
<span>This will only render for authenticated users</span>
</ AuthenticatedTemplate>
<UnauthenticatedTemplate>
<span>This will only render for unauthenticated users</span>
</ UnauthenticatedTemplate>
<MsalAuthenticationTemplate interactionType={InteractionType.Popup}>
<span>This will only render for authenticated users.</span>
</ MsalAuthenticationTemplate>
</ MsalProvider>
);
}
}
在类组件中获取 MSAL React 上下文
useMsal挂钩不能用于访问类组件中的 MSAL React 上下文。 这是因为 Hook 只能在函数组件中使用,而在函数组件中,你可以在没有实例的情况下使用这些功能。 由于类组件具有实例,因此有 2 个其他选项。 你既可以直接使用原始上下文,也可以使用 withMsal 高阶组件将上下文注入到组件的 props 中。
访问原始上下文
以下代码片段演示如何使用该 MsalContext 代码片段访问类组件中的原始上下文。
import React from "react";
import { MsalProvider, MsalContext } from "@azure/msal-react";
import { PublicClientApplication } from "@azure/msal-browser";
const pca = new PublicClientApplication(config);
class App extends React.Component {
render() {
return (
<MsalProvider instance={pca}>
<YourClassComponent/>
</ MsalProvider>
);
}
}
class YourClassComponent extends React.Component {
static contextType = MsalContext;
render() {
const isAuthenticated = this.context.accounts.length > 0;
if (isAuthenticated) {
return <span>There are currently {this.context.accounts.length} users signed in!</span>
}
}
}
有关工作示例,请参阅 react-router-sample 中的 ProfileRawContext.jsx。
通过 withMsal 高阶组件 (HOC) 访问
另一种方法是使用 withMsal 高阶组件,将上下文注入到组件的 props 中。 以下代码片段演示如何使用 withMsal HOC 访问类组件中的 MSAL React 上下文。
import React from "react";
import { MsalProvider, withMsal } from "@azure/msal-react";
import { PublicClientApplication } from "@azure/msal-browser";
const pca = new PublicClientApplication(config);
class YourClassComponent extends React.Component {
render() {
const isAuthenticated = this.props.msalContext.accounts.length > 0;
if (isAuthenticated) {
return <span>There are currently {this.props.msalContext.accounts.length} users signed in!</span>
}
}
}
const YourWrappedComponent = withMsal(YourClassComponent);
class App extends React.Component {
render() {
return (
<MsalProvider instance={pca}>
<YourWrappedComponent />
</ MsalProvider>
);
}
}
有关工作示例,请参阅 react-router-sample 中的 ProfileWithMsal.jsx。
使用类组件进行登录
无论采用哪种方法来获取 MSAL React 上下文,使用情况都将相同。 获得上下文对象后,可以调用任何 APIPublicClientApplication,检查登录的帐户,或确定身份验证当前是否正在进行。
以下示例演示如何使用 withMsal HOC 方法登录,但如果需要,可以快速适应其他方法。
注释
请务必记住,对于任何使用上下文的组件,都必须在其上层某一级渲染一个 MsalProvider 组件。 以下示例假设存在提供程序,因此不会演示这一点。
单击按钮后登录
以下代码片段定义使用LoginButton高阶组件的 React 类组件withMsal。 它呈现一个按钮,该按钮在用户未进行身份验证时触发登录弹出窗口,或者注销用户(如果已经过身份验证)。
import React from "react";
import { withMsal } from "@azure/msal-react";
class LoginButton extends React.Component {
render() {
const isAuthenticated = this.props.msalContext.accounts.length > 0;
const msalInstance = this.props.msalContext.instance;
if (isAuthenticated) {
return <button onClick={() => msalInstance.logout()}>Logout</button>
} else {
return <button onClick={() => msalInstance.loginPopup()}>Login</button>
}
}
}
export default YourWrappedComponent = withMsal(LoginButton);
在页面加载时登录
以下代码片段定义使用ProtectedComponent高阶组件的 React 类组件withMsal。 它尝试在装载和更新时对用户进行身份验证,并显示用户是否已进行身份验证,或者是否正在加载页面上进行身份验证。
import React from "react";
import { withMsal } from "@azure/msal-react";
import { InteractionStatus } from "@azure/msal-browser";
class ProtectedComponent extends React.Component {
callLogin() {
const isAuthenticated = this.props.msalContext.accounts.length > 0;
const msalInstance = this.props.msalContext.instance;
// If a user is not logged in and authentication is not already in progress, invoke login
if (!isAuthenticated && this.props.msalContext.inProgress === InteractionStatus.None) {
msalInstance.loginPopup();
}
}
componentDidMount() {
this.callLogin();
}
componentDidUpdate() {
this.callLogin();
}
render() {
const isAuthenticated = this.props.msalContext.accounts.length > 0;
if (isAuthenticated) {
return <span>User is authenticated</span>
} else {
return <span>Authentication in progress</span>;
}
}
}
export default YourWrappedComponent = withMsal(ProtectedComponent);
另见
- 查看我们的react-router-sample。