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

如何通过AWS Cognito关联RDS实现用户数据权限控制与自动创建

解决Cognito与RDS集成的两个核心问题

一、限制RDS记录仅对应Cognito用户可访问

核心思路

  1. 在RDS业务表中新增cognito_user_id字段,存储用户的Cognito唯一ID(即sub属性),建立用户与数据的关联;
  2. 后端API先验证请求中的Cognito JWT令牌,解析出用户的sub标识;
  3. 查询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();
  }
};

关键注意事项

  1. 给Lambda函数配置IAM角色,使其拥有RDS的访问权限(推荐使用最小权限原则,而非全量权限);
  2. Lambda需部署在与RDS同VPC的子网中,或调整RDS安全组允许Lambda的IP访问;
  3. 若使用MySQL,需在Lambda层添加mysql2依赖包,避免函数包体积过大。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:15:28