如何通过AWS Cognito关联RDS实现用户数据权限控制与自动创建
解决Cognito与RDS集成的两个核心问题
一、限制RDS记录仅对应Cognito用户可访问
核心思路
- 在RDS业务表中新增
cognito_user_id字段,存储用户的Cognito唯一ID(即sub属性),建立用户与数据的关联; - 后端API先验证请求中的Cognito JWT令牌,解析出用户的
sub标识; - 查询RDS数据时,强制带上
cognito_user_id = 当前用户sub的过滤条件,确保用户只能访问自身数据。
Node.js代码示例
1. Cognito JWT验证中间件(Express框架)
const jwt = require('jsonwebtoken'); const jwksClient = require('jwks-rsa'); // 替换为你的Cognito用户池信息 const client = jwksClient({ jwksUri: 'https://cognito-idp.<你的区域>.amazonaws.com/<你的用户池ID>/.well-known/jwks.json' }); function getKey(header, callback) { client.getSigningKey(header.kid, function(err, key) { const signingKey = key.getPublicKey(); callback(null, signingKey); }); } // 验证Cognito令牌的中间件 exports.verifyCognitoToken = (req, res, next) => { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ error: '未提供有效令牌' }); } const token = authHeader.split(' ')[1]; jwt.verify(token, getKey, { audience: '<你的App Client ID>', issuer: 'https://cognito-idp.<你的区域>.amazonaws.com/<你的用户池ID>' }, (err, decoded) => { if (err) { return res.status(403).json({ error: '令牌验证失败' }); } // 将解析后的用户信息挂载到请求对象 req.user = decoded; next(); }); };
2. 带权限过滤的RDS查询代码
const mysql = require('mysql2/promise'); // RDS数据库连接配置 const dbConfig = { host: '<你的RDS端点>', user: '<数据库用户名>', password: '<数据库密码>', database: '<数据库名>' }; // 获取当前用户的私有数据 exports.getUserPrivateData = async (req, res) => { const userId = req.user.sub; // 从验证后的令牌中提取用户sub let connection; try { connection = await mysql.createConnection(dbConfig); // 查询时强制过滤用户ID,仅返回当前用户的私有数据 const [rows] = await connection.execute( 'SELECT * FROM user_data WHERE cognito_user_id = ? AND is_public = 0', [userId] ); res.status(200).json(rows); } catch (err) { res.status(500).json({ error: '数据库查询失败', details: err.message }); } finally { if (connection) await connection.end(); } }; // 获取所有公开数据 exports.getPublicData = async (req, res) => { let connection; try { connection = await mysql.createConnection(dbConfig); const [rows] = await connection.execute( 'SELECT * FROM user_data WHERE is_public = 1' ); res.status(200).json(rows); } catch (err) { res.status(500).json({ error: '数据库查询失败', details: err.message }); } finally { if (connection) await connection.end(); } };
二、新Cognito用户创建时自动在RDS添加对应记录
核心思路
利用Cognito的Post Confirmation触发器:当用户完成注册确认后,Cognito会自动调用指定的Lambda函数,在Lambda中编写代码连接RDS,插入新用户的基础记录。
Node.js代码示例(Lambda函数)
const mysql = require('mysql2/promise'); // RDS数据库连接配置 const dbConfig = { host: '<你的RDS端点>', user: '<数据库用户名>', password: '<数据库密码>', database: '<数据库名>' }; exports.handler = async (event) => { // 从Cognito触发器事件中提取用户核心信息 const userSub = event.request.userAttributes.sub; const email = event.request.userAttributes.email; let connection; try { connection = await mysql.createConnection(dbConfig); // 插入用户基础记录到RDS用户表 await connection.execute( 'INSERT INTO users (cognito_user_id, email, created_at) VALUES (?, ?, NOW())', [userSub, email] ); return event; // 必须返回event,否则Cognito注册流程会异常 } catch (err) { console.error('插入用户记录失败:', err); throw err; // 抛出错误会触发Cognito的重试机制 } finally { if (connection) await connection.end(); } };
关键注意事项
- 给Lambda函数配置IAM角色,使其拥有RDS的访问权限(推荐使用最小权限原则,而非全量权限);
- Lambda需部署在与RDS同VPC的子网中,或调整RDS安全组允许Lambda的IP访问;
- 若使用MySQL,需在Lambda层添加
mysql2依赖包,避免函数包体积过大。
内容的提问来源于stack exchange,提问作者Ewan Boyle
相关产品推荐
相关产品推荐

