从AWS Cognito获取认证令牌后该如何处理?
AWS Cognito令牌处理、登录状态管理及路由控制实践指导
一、令牌存储的正确姿势
你现在只存在状态变量里的问题很明显:页面一刷新状态就丢了,用户得重新登录,体验拉胯。但直接丢localStorage也有安全风险,分令牌给你说:
- Access Token/ID Token:可以同时存在「应用状态(比如React Context/Redux)」+「localStorage(或sessionStorage)」。页面加载时先从localStorage读令牌,恢复登录状态。但要注意XSS风险——localStorage是同源可访问的,XSS脚本能直接窃取,所以必须配合XSS防护(比如设置Content-Security-Policy头、过滤用户输入)。如果想降低风险,用sessionStorage代替localStorage,关闭浏览器就自动清除。
- Refresh Token:绝对不能存localStorage!这玩意儿有效期长(默认30天),被盗了危害极大。纯前端SPA的话,最好存在内存状态里,页面刷新后丢失就让用户重新登录,牺牲一点体验换安全。如果必须持久化,得后端配合把它存到HttpOnly、Secure、SameSite=Strict的Cookie里,前端拿不到,能避免XSS窃取。
二、登录状态维持
- 应用启动时(比如入口组件初始化),先检查localStorage里的令牌:
- 用
jwt-decode解析ID Token的exp字段(注意是时间戳,要转成毫秒和当前时间对比),判断是否过期。 - 令牌有效就加载到应用状态,标记用户已登录;过期或不存在就清空存储,跳登录页。
- 用
- 平时API调用前,也先校验Access Token的有效期,避免发无效请求。
三、路由访问控制
给需要登录的路由加个守卫组件就行,核心逻辑是「验证令牌有效性」,而不是只看状态变量(状态可能被篡改)。举个React的例子:
import { Navigate } from 'react-router-dom'; import jwtDecode from 'jwt-decode'; import { useAuthContext } from './auth-context'; const PrivateRoute = ({ children }) => { const { idToken } = useAuthContext(); // 验证令牌是否存在且未过期 const isTokenValid = idToken ? jwtDecode(idToken).exp * 1000 > Date.now() : false; if (!idToken || !isTokenValid) { return <Navigate to="/login" replace />; } return children; };
用的时候直接把需要保护的路由包在PrivateRoute里就行。
四、令牌过期与刷新逻辑
别等令牌过期了才处理,提前几分钟(比如5分钟)触发刷新更丝滑:
- 解析令牌的
exp字段,计算提前刷新的时间点,用定时器触发刷新。 - 用Refresh Token调用Cognito的
RefreshTokenCommand获取新的Access Token和ID Token,有些场景还会返回新的Refresh Token,记得一起更新。 - 刷新成功就更新应用状态和localStorage里的令牌;刷新失败(比如Refresh Token过期),直接清空所有令牌,跳登录页。
示例代码(AWS SDK v3):
import { CognitoIdentityProviderClient, RefreshTokenCommand } from "@aws-sdk/client-cognito-identity-provider"; const cognitoClient = new CognitoIdentityProviderClient({ region: '你的区域' }); export const refreshAuthTokens = async (refreshToken) => { try { const command = new RefreshTokenCommand({ ClientId: '你的Cognito客户端ID', RefreshToken: refreshToken, }); const { AuthenticationResult } = await cognitoClient.send(command); return { accessToken: AuthenticationResult.AccessToken, idToken: AuthenticationResult.IdToken, refreshToken: AuthenticationResult.RefreshToken || refreshToken, }; } catch (err) { console.error('令牌刷新失败:', err); throw err; // 抛出错误让上层处理登出 } };
五、额外要注意的点
- 不要完全依赖前端的令牌校验:API Gateway本身会验证令牌的有效性,但前端提前校验能减少无效请求。
- 注销要彻底:用户点击注销时,除了清空localStorage和应用状态,最好调用Cognito的
GlobalSignOutCommand让Refresh Token失效,防止被盗用。 - XSS防护是必须的:只要用了localStorage,就一定要做XSS防护,比如设置CSP头、避免使用
eval等危险函数、过滤用户输入内容。
内容的提问来源于stack exchange,提问作者Just Another Programmer
相关产品推荐
相关产品推荐

