如何在AWS环境下实现React网站获取用户数据?
React + AWS Cognito + RDS 实现登录后获取个人数据方案
你的核心思路方向正确,仅数据库表设计需要调整,先明确完整可行的流程:
- 用户通过Cognito登录后,回调URL会携带授权码或直接返回JWT令牌
- 前端获取并存储令牌,解码得到用户的唯一标识(推荐用Cognito分配的
sub字段,比邮箱更稳定) - 前端携带令牌调用已配置的API Gateway,触发关联的Lambda函数
- Lambda验证令牌合法性后,连接RDS查询该用户对应的数据,返回给前端渲染表格
疑问解答
1. JWT令牌的获取与API调用
获取JWT令牌
- 若使用Cognito Hosted UI,回调URL会收到
code参数,前端需用该code向Cognito令牌端点(https://你的Cognito域名/oauth2/token)发起POST请求,换取Access Token和ID Token(优先用Access Token调用API) - 拿到令牌后,存在
sessionStorage(短期会话更安全,避免XSS长期泄露)或localStorage中
API调用携带令牌
每次调用API Gateway都必须携带令牌,放在请求头的Authorization字段,格式为Bearer <Access Token>。React中示例代码:
const fetchUserData = async () => { const token = sessionStorage.getItem('accessToken'); const res = await fetch('你的API Gateway访问URL', { method: 'GET', headers: { 'Authorization': `Bearer ${token}` } }); const userData = await res.json(); // 渲染表格逻辑 };
API Gateway的Cognito授权会自动验证令牌有效性,验证通过才会触发Lambda。
2. 数据库实例设计
绝对不要给每个用户单独建表,这是数据库设计的反模式,会导致维护成本剧增。正确设计:
- 创建一张统一的用户业务数据表,比如
user_biz_data - 核心字段包含:
id(自增主键)user_sub(Cognito用户的永久唯一标识sub,非空,建立索引)email(可选,作为冗余字段)- 其他业务相关字段(如
nickname,record_date,content等)
- 查询时用
user_sub作为条件,比邮箱更可靠(用户可能修改邮箱,但sub不会变更)
3. 使用AWS Amplify vs 不使用的实现方案
方案一:使用AWS Amplify(简化开发)
Amplify已封装Cognito、API Gateway的集成逻辑,大幅减少代码量:
- 关联现有AWS资源:
amplify init amplify add auth # 选择关联已有的Cognito用户池 amplify add api # 选择关联已有的API Gateway amplify push
- React端核心代码:
import { Auth, API } from 'aws-amplify'; // 跳转Cognito Hosted UI登录 const handleSignIn = async () => { await Auth.federatedSignIn(); }; // 获取用户数据 const getUserData = async () => { const user = await Auth.currentAuthenticatedUser(); const token = user.signInUserSession.accessToken.jwtToken; const data = await API.get('你的API名称', '/数据接口路径', { headers: { Authorization: `Bearer ${token}` } }); // 渲染表格 };
- Lambda连接RDS代码:
const mysql = require('mysql2/promise'); exports.handler = async (event) => { // API Gateway授权后,用户sub会自动存放在该字段 const userSub = event.requestContext.authorizer.claims.sub; // 建立RDS连接(建议用Secrets Manager存储数据库凭证,避免硬编码) const conn = await mysql.createConnection({ host: '你的RDS端点', user: '数据库用户名', password: '数据库密码', database: '目标数据库名' }); // 查询用户数据 const [rows] = await conn.execute('SELECT * FROM user_biz_data WHERE user_sub = ?', [userSub]); await conn.end(); return { statusCode: 200, body: JSON.stringify(rows) }; };
方案二:不使用AWS Amplify(手动实现)
- 前端处理登录与令牌获取:
// 回调页面处理授权码换令牌 const handleCallback = async () => { const code = new URLSearchParams(window.location.search).get('code'); const tokenRes = await fetch('https://你的Cognito域名/oauth2/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', client_id: '你的Cognito应用客户端ID', code, redirect_uri: '你的回调URL' }) }); const tokens = await tokenRes.json(); sessionStorage.setItem('accessToken', tokens.access_token); // 重定向到应用页 window.location.href = '/app'; }; // 应用页调用API const fetchUserData = async () => { const token = sessionStorage.getItem('accessToken'); const res = await fetch('你的API Gateway访问URL', { method: 'GET', headers: { 'Authorization': `Bearer ${token}` } }); const userData = await res.json(); // 渲染表格逻辑 };
- Lambda连接RDS的代码与方案一完全一致,API Gateway已完成令牌验证,Lambda可直接读取
event.requestContext.authorizer.claims.sub获取用户标识
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

