求助:实现AWS Cognito预认证Lambda触发器(查询外部DB用户订阅)
AWS Cognito预认证Lambda触发器查询外部数据库示例
以下是Node.js版本的Lambda示例,用于在Cognito预认证阶段查询外部数据库(以MySQL为例)验证用户订阅状态:
1. 前提准备
- 确保Lambda函数配置了访问目标数据库的权限:
- 将Lambda部署到与数据库同VPC的子网中
- 安全组允许Lambda访问数据库端口(如MySQL的3306)
- 为Lambda添加对应IAM权限(若用IAM认证数据库需额外配置)
- 在Lambda层或代码包中包含数据库驱动(如
mysql2)
2. Lambda代码示例
const mysql = require('mysql2/promise'); // 数据库连接配置(建议用环境变量存储敏感信息) const dbConfig = { host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, port: 3306 }; // 创建连接池(避免每次请求新建连接) const pool = mysql.createPool(dbConfig); exports.handler = async (event) => { // 从Cognito事件中提取待认证用户标识(如用户名或邮箱,依用户池配置而定) const userId = event.request.userName; // 也可使用 event.request.userAttributes.email let connection; try { // 获取数据库连接 connection = await pool.getConnection(); // 查询用户订阅信息 const [rows] = await connection.execute( 'SELECT subscription_status, subscription_expiry FROM user_subscriptions WHERE user_id = ?', [userId] ); if (rows.length === 0) { // 用户无订阅记录,阻止认证 return { response: { failAuthentication: true, message: "未找到用户订阅信息,无法完成认证" } }; } const userSubscription = rows[0]; if (userSubscription.subscription_status !== 'active' || new Date(userSubscription.subscription_expiry) < new Date()) { // 订阅已过期或未激活,阻止认证 return { response: { failAuthentication: true, message: "订阅已过期或未激活,请重新订阅" } }; } // 订阅有效,允许认证,可添加自定义属性到用户会话 return { response: { allowAuthentication: true, // 可选:添加自定义属性到Cognito用户会话 claimsOverrideDetails: { claimsToAddOrOverride: { subscription_level: 'premium', subscription_expiry: userSubscription.subscription_expiry } } } }; } catch (error) { console.error('查询订阅信息失败:', error); // 数据库查询出错时,阻止认证并返回提示 return { response: { failAuthentication: true, message: "认证过程中出现错误,请稍后重试" } }; } finally { // 释放连接回池 if (connection) connection.release(); } };
3. 关键注意事项
- 敏感信息存储:不要硬编码数据库账号密码,用Lambda环境变量配置
DB_HOST、DB_USER等参数 - 连接池优化:使用连接池而非每次新建连接,避免数据库连接耗尽
- 响应格式要求:必须返回符合Cognito规范的结构,
allowAuthentication或failAuthentication二选一 - 错误处理:捕获数据库查询异常,避免Lambda执行报错导致Cognito认证流程中断
- 用户标识匹配:确保查询用的
user_id与Cognito中的用户标识(如用户名、邮箱)一致,需提前在外部数据库同步该标识
内容的提问来源于stack exchange,提问作者Marwenv1
相关产品推荐
相关产品推荐

