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

React应用中如何处理AWS Cognito Refresh Token?

React端AWS Cognito令牌管理与会话维持方案

一、令牌的安全存储

  • 别用localStorage存令牌,容易遭XSS攻击窃取,优先用sessionStorage——关闭浏览器标签就自动清除,安全性更高;如果后端支持,最好把令牌存在HttpOnly + Secure Cookie里,完全规避前端JS访问的风险。
  • 登录成功后,把Cognito返回的accessToken、idToken、refreshToken打包成JSON存在sessionStorage,同时存一下当前用户名(后续刷新会话要用)。

二、检查令牌有效性

1. 解析JWT手动判断过期

Cognito的accessToken和idToken都是JWT格式,直接解析payload里的exp字段(Unix时间戳)对比当前时间就行:

// 解析JWT的工具函数
const parseJwt = (token) => {
  try {
    return JSON.parse(atob(token.split('.')[1]));
  } catch (e) {
    return null;
  }
};

// 检查令牌是否过期
const isTokenExpired = (token) => {
  if (!token) return true;
  const decoded = parseJwt(token);
  if (!decoded?.exp) return true;
  return decoded.exp * 1000 < Date.now();
};
  • 每次发API请求前先跑这个检查,过期了就去刷新令牌。

2. 用Cognito SDK自带方法验证

如果用amazon-cognito-identity-js,可以直接用CognitoUserSession.isValid()方法验证整个会话的有效性:

import { CognitoUserSession } from 'amazon-cognito-identity-js';

// 从存储里取令牌构建会话对象
const storedSession = JSON.parse(sessionStorage.getItem('cognitoSession'));
const session = new CognitoUserSession({
  IdToken: storedSession.idToken,
  AccessToken: storedSession.accessToken,
  RefreshToken: storedSession.refreshToken,
});

// 检查会话是否有效
const isSessionValid = session.isValid();

三、用RefreshToken刷新会话

当accessToken或idToken过期时,调用Cognito SDK的refreshSession方法获取新令牌:

import { CognitoUser } from 'amazon-cognito-identity-js';
import { userPool } from './your-cognito-config'; // 提前配置好的用户池实例

// 获取当前登录的Cognito用户对象
const getCurrentCognitoUser = () => {
  const username = sessionStorage.getItem('cognitoUsername');
  return new CognitoUser({ Username: username, Pool: userPool });
};

// 刷新会话的异步方法
const refreshCognitoSession = async () => {
  const cognitoUser = getCurrentCognitoUser();
  const storedRefreshToken = JSON.parse(sessionStorage.getItem('cognitoSession')).refreshToken;

  return new Promise((resolve, reject) => {
    cognitoUser.refreshSession(storedRefreshToken, (err, newSession) => {
      if (err) {
        // 刷新失败,比如refreshToken过期了,直接踢去登录页
        reject(err);
        return;
      }
      // 更新存储里的令牌
      const updatedTokens = {
        accessToken: newSession.getAccessToken().getJwtToken(),
        idToken: newSession.getIdToken().getJwtToken(),
        refreshToken: newSession.getRefreshToken().getToken(),
      };
      sessionStorage.setItem('cognitoSession', JSON.stringify(updatedTokens));
      resolve(newSession);
    });
  });
};

四、会话维持的落地实践

  • 统一请求拦截:在Axios或者Fetch的请求拦截器里处理令牌检查和刷新,避免每个请求都写一遍逻辑:
// Axios拦截器示例
import axios from 'axios';

let isRefreshing = false; // 防止多个请求同时触发刷新
let refreshQueue = [];

axios.interceptors.request.use(async (config) => {
  const storedSession = sessionStorage.getItem('cognitoSession');
  if (!storedSession) {
    window.location.href = '/login';
    return Promise.reject(new Error('未检测到会话'));
  }

  const session = JSON.parse(storedSession);
  if (isTokenExpired(session.accessToken)) {
    if (isRefreshing) {
      // 等待当前刷新完成
      return new Promise((resolve) => {
        refreshQueue.push(() => resolve(config));
      });
    }
    isRefreshing = true;
    try {
      await refreshCognitoSession();
      const updatedSession = JSON.parse(sessionStorage.getItem('cognitoSession'));
      config.headers.Authorization = `Bearer ${updatedSession.accessToken}`;
      // 处理队列里的请求
      refreshQueue.forEach(callback => callback(config));
      refreshQueue = [];
    } catch (err) {
      sessionStorage.removeItem('cognitoSession');
      sessionStorage.removeItem('cognitoUsername');
      window.location.href = '/login';
      return Promise.reject(err);
    } finally {
      isRefreshing = false;
    }
  } else {
    config.headers.Authorization = `Bearer ${session.accessToken}`;
  }
  return config;
});
  • 路由守卫:用React Router的导航守卫(比如在路由组件里加useEffect,或者用Navigate组件),每次跳转前检查会话有效性,过期就跳登录页。
  • RefreshToken有效期:Cognito默认给refreshToken设30天有效期,你可以在用户池的“应用客户端设置”里调整,一旦refreshToken过期,必须让用户重新登录(包括MFA验证)。

五、关键注意事项

  • 绝对不要把refreshToken存在localStorage里,XSS攻击很容易窃取,导致账号被盗。
  • 前端的令牌检查只是为了提升用户体验,后端API必须自己验证accessToken的有效性(比如通过Cognito的JWKS端点校验签名和过期时间),不能完全信任前端的判断。
  • MFA登录后的会话处理和普通登录完全一致,用refreshToken刷新时不需要重新输入MFA验证码,除非你的用户池配置了强制MFA刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:37:50