umi4 实现msal aad 登录loginPopup方式并获取令牌

本文介绍了如何在UMI4应用中集成MSAL库,实现AzureActiveDirectory(AAD)的登录功能,并获取及管理访问令牌。通过创建AzureAD应用,配置msal实例,以及设置Axios拦截器自动添加和刷新令牌,确保安全地访问受保护资源。
摘要由CSDN通过智能技术生成

为了在 UMI 4 中实现 MSAL AAD 登录并获取访问令牌,你可以按照以下步骤操作:

  1. 首先,在 Azure 门户中创建一个 Azure Active Directory 应用程序。记录应用程序的客户端 ID 和租户 ID,稍后将在配置中使用。
  2. 在你的 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 函数将抛出异常。你可以在拦截器中或组件内处理这些异常,例如引导用户重新登录。

umi4 中,可以使用 `@umijs/plugin-model` 插件来管理全局状态,包括使用 modal 的方式。具体步骤如下: 1. 安装 `@umijs/plugin-model` 插件: ```bash npm install @umijs/plugin-model --save-dev ``` 2. 在 `.umirc.ts` 中配置插件: ```typescript export default { // ... plugins: ['@umijs/plugin-model'], }; ``` 3. 创建一个 modal 文件,例如 `src/models/user.ts`: ```typescript import { Effect, Reducer } from 'umi'; export interface UserModelState { name: string; } export interface UserModelType { namespace: 'user'; state: UserModelState; effects: { fetch: Effect; }; reducers: { save: Reducer<UserModelState>; }; } const UserModel: UserModelType = { namespace: 'user', state: { name: '', }, effects: { *fetch(_, { call, put }) { // 请求用户信息 const data = yield call(fetchUser); // 更新用户信息 yield put({ type: 'save', payload: data, }); }, }, reducers: { save(state, { payload }) { return { ...state, ...payload, }; }, }, }; export default UserModel; function fetchUser() { return Promise.resolve({ name: 'Tom' }); } ``` 4. 在页面中使用 `useModel` 函数来访问 modal 数据: ```tsx import { useModel } from 'umi'; import styles from './index.less'; export default function IndexPage() { const { initialState, loading, error } = useModel('user'); const { name } = initialState; return ( <div className={styles.container}> {loading ? ( <div>Loading...</div> ) : error ? ( <div>Error: {error.message}</div> ) : ( <div>Hello, {name}!</div> )} </div> ); } ``` 通过上面的步骤,就可以在 umi4 中使用 modal 来管理全局状态了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jim-zf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值