You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于AWS Cognito SDK的React应用:如何用刷新后的JWT令牌调用API?

实现AWS Cognito刷新JWT令牌并调用API的React方案

看了你当前的代码,你现在是在componentWillMount里做会话检查,但要实现自动刷新JWT令牌并安全调用API的话,咱们可以基于AWS Cognito的SDK(推荐用Amplify封装的版本,更省心)来调整逻辑,同时把一些不安全的生命周期方法替换掉。

核心思路

AWS Cognito的JS SDK其实自带了令牌刷新的能力,我们只需要利用Auth.currentSession()方法——它会自动检查访问令牌是否过期,如果过期且刷新令牌有效,就会自动去获取新的访问令牌和ID令牌。我们要做的就是在调用API前确保拿到的是有效令牌,然后把它放到请求头里。

具体实现步骤(类组件版本)

首先,确保你已经安装并配置了AWS Amplify(如果还没的话,先跑npm install aws-amplify并配置你的Cognito信息)。

  1. 封装获取有效令牌的函数
    在你的组件里添加一个异步函数,用来获取或刷新令牌:
import { Auth } from 'aws-amplify';

class YourComponent extends React.Component {
  // 获取有效访问令牌,自动处理刷新
  async getValidAccessToken() {
    try {
      const session = await Auth.currentSession();
      const accessToken = session.getAccessToken();
      // 可以提前检查令牌是否即将过期(比如提前5分钟),主动刷新
      const expiresAtMs = accessToken.getExpiration() * 1000; // 转成毫秒
      if (Date.now() > expiresAtMs - 300000) {
        // 强制刷新会话
        const refreshedSession = await Auth.refreshSession(session.getRefreshToken());
        return refreshedSession.getAccessToken().getJwtToken();
      }
      // 令牌还没过期,直接返回
      return accessToken.getJwtToken();
    } catch (error) {
      // 刷新失败(比如刷新令牌也过期了),跳转到登录页
      this.props.history.push('/auth/login');
      throw error; // 抛出错误让上层处理
    }
  }
  1. 替换生命周期方法
    React官方已经标记componentWillMount为不安全,建议换成componentDidMount,然后在里面初始化用户信息和令牌:
componentDidMount() {
    if (!this.props.authenticated) {
      this.props.history.push('/auth/login');
      return;
    }
    // 初始化用户和令牌
    this.initUserAndToken();
  }

  async initUserAndToken() {
    try {
      // 获取当前认证用户的信息
      const user = await Auth.currentAuthenticatedUser();
      // 同步到Redux状态
      this.props.setUserToReduxState(user.attributes);
      
      // 获取有效令牌
      const accessToken = await this.getValidAccessToken();
      // 把令牌存到组件state,方便后续API调用
      this.setState({ accessToken }, () => {
        // 现在可以调用你的API了
        this.callYourAPI();
      });
    } catch (error) {
      console.error('初始化用户和令牌失败:', error);
      this.props.history.push('/auth/login');
    }
  }
  1. 带令牌调用API
    在你的API调用函数里,把令牌放到Authorization请求头:
async callYourAPI() {
    const { accessToken } = this.state;
    if (!accessToken) return;

    try {
      const response = await fetch('/your-api-endpoint', {
        method: 'GET', // 或者POST/PUT等
        headers: {
          'Authorization': `Bearer ${accessToken}`,
          'Content-Type': 'application/json'
        }
      });
      const data = await response.json();
      // 处理API返回的数据
      console.log('API返回数据:', data);
    } catch (error) {
      console.error('API调用失败:', error);
    }
  }
}

额外优化建议

  • 复用逻辑:可以把令牌刷新的逻辑封装成高阶组件(HOC)或者自定义Hook,这样多个组件都能复用,不用重复写代码。比如自定义Hook版本:
import { useState, useEffect } from 'react';
import { Auth } from 'aws-amplify';

export const useValidAccessToken = () => {
  const [accessToken, setAccessToken] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchToken = async () => {
      try {
        const session = await Auth.currentSession();
        const accessToken = session.getAccessToken();
        const expiresAtMs = accessToken.getExpiration() * 1000;
        if (Date.now() > expiresAtMs - 300000) {
          const refreshedSession = await Auth.refreshSession(session.getRefreshToken());
          setAccessToken(refreshedSession.getAccessToken().getJwtToken());
        } else {
          setAccessToken(accessToken.getJwtToken());
        }
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchToken();
  }, []);

  return { accessToken, loading, error };
};

在函数组件里直接用这个Hook就能拿到有效令牌,还能处理加载和错误状态。

  • 自动拦截API请求:可以用Axios的拦截器,在所有API请求前自动获取有效令牌并添加到请求头,这样每个API调用不用手动加头,更方便。比如:
import axios from 'axios';
import { Auth } from 'aws-amplify';

const api = axios.create({ baseURL: '/your-api-base-url' });

// 请求拦截器
api.interceptors.request.use(async (config) => {
  const session = await Auth.currentSession();
  const accessToken = session.getAccessToken().getJwtToken();
  config.headers.Authorization = `Bearer ${accessToken}`;
  return config;
}, (error) => {
  return Promise.reject(error);
});

// 然后用api.get('/endpoint')调用,自动带令牌

内容的提问来源于stack exchange,提问作者dankthreads

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:30:02