为了在 UMI 4 中实现 MSAL AAD 登录并获取访问令牌,你可以按照以下步骤操作:
- 首先,在 Azure 门户中创建一个 Azure Active Directory 应用程序。记录应用程序的客户端 ID 和租户 ID,稍后将在配置中使用。
- 在你的 UMI 项目中安装
msal
包:
yarn add msal
或npm install msal
3. 在 UMI 项目中创建一个名为 azureAuth.js
的新文件,然后在文件中设置 MSAL 的配置:
import {UserAgentApplication} from "msal";
const msalConfig = {
auth: {
clientId: '你的客户端 ID',
authority: 'https://login.microsoftonline.com/你的租户 ID',
redirectUri: '你的重定向 URI',
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true,
},
};
export const msalInstance = new UserAgentApplication(msalConfig);
// 获取token
export async function getAccessToken() {
try {
const account = msalInstance.getAccount();
if (!account) {
throw new Error('用户未登录');
}
const request = {
scopes: ['openid', 'profile', 'User.Read'], // 添加你需要的权限
// scopes: [msalConfig?.auth.scope],
account,
};
const response = await msalInstance.acquireTokenSilent(request);
return response.accessToken;
} catch (error) {
console.error("获取访问令牌失败", error);
throw error;
}
}
4. 创建一个名为 Login.jsx
的组件,导入 azureAuth.js
,并调用登录方法:
import React from 'react';
import msalInstance from './azureAuth';
const Login = () => {
const handleLogin = () => {
msalInstance.loginPopup()
.then(response => {
console.log('登录成功', response);
})
.catch(error => {
console.log('登录失败', error);
});
};
return (
<div>
<button onClick={handleLogin}>登录</button>
</div>
);
};
export default Login;
5. 在需要获取访问令牌的组件(例如在受保护资源的组件中):
import React, { useEffect, useState } from 'react';
import msalInstance from './azureAuth';
const ProtectedResource = () => {
const [accessToken, setAccessToken] = useState(null);
useEffect(() => {
const account = msalInstance.getAccount();
if (account) {
const request = {
scopes: ['openid', 'profile', 'User.Read'], // 添加你需要的权限
account: account,
};
msalInstance.acquireTokenSilent(request)
.then(response => {
setAccessToken(response.accessToken);
})
.catch(error => {
console.error('获取访问令牌失败', error);
});
} else {
console.log('用户未登录');
}
}, []);
return (
<div>
{accessToken && (
<div>
<h3>访问令牌:</h3>
<p>{accessToken}</p>
</div>
)}
</div>
);
};
export default ProtectedResource;
在这个示例中,我们首先使用 msalInstance.getAccount()
获取用户信息。然后,我们使用 msalInstance.acquireTokenSilent()
获取访问令牌,并将其保存在 accessToken
状态变量中。这样,我们就可以在组件中显示访问令牌,并根据需要访问受保护的资源。
二、按照上述在asiox请求种如果add token过期需要刷新add 令牌
为了在 Axios 请求中添加访问令牌并在过期时刷新它,可以使用 Axios 的拦截器。
接下来,在项目中创建一个名为 api.js
的新文件,用于设置 Axios 拦截器:
import axios from 'axios';
import { getAccessToken } from './azureAuth';
const apiClient = axios.create();
apiClient.interceptors.request.use(
async (config) => {
try {
const accessToken = await getAccessToken();
config.headers.Authorization = `Bearer ${accessToken}`;
} catch (error) {
console.error('添加访问令牌失败', error);
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
export default apiClient;
现在,你可以在项目中使用 apiClient
发送请求,它会自动添加访问令牌到请求头中。如果访问令牌过期,msalInstance.acquireTokenSilent()
方法会自动尝试刷新令牌。
在需要使用 Axios 的组件中,导入 api.js
并使用 apiClient
发送请求:
import React, { useEffect } from 'react';
import apiClient from './api';
const ExampleComponent = () => {
useEffect(() => {
apiClient
.get('https://example.com/protected-resource')
.then((response) => {
console.log('请求成功', response.data);
})
.catch((error) => {
console.error('请求失败', error);
});
}, []);
return <div>Example Component</div>;
};
export default ExampleComponent;
这样,在发送请求时,访问令牌会被自动添加到请求头中,并在过期时自动刷新。请注意,如果刷新令牌失败或用户未登录,getAccessToken
函数将抛出异常。你可以在拦截器中或组件内处理这些异常,例如引导用户重新登录。