如何在Lambda函数中验证Cognito会话以获取DynamoDB数据?
嘿,刚好有经验处理这个场景!你已经用Amplify搞定了Cognito用户认证,现在要在Lambda里验证会话有效性,其实核心是验证Cognito返回的ID Token或者Access Token的合法性,下面给你两种靠谱的实现方式:
方法一:用AWS SDK调用Cognito官方API验证(简单直接)
这种方式最省心,AWS会帮你处理所有验证逻辑(比如令牌签名、过期时间、权限校验等),你只需要调用CognitoIdentityServiceProvider的getUser方法,传入用户的Access Token就行。
步骤:
- 前端传令牌到Lambda:Amplify认证成功后,你可以通过
Auth.currentSession()拿到会话中的accessToken.jwtToken,把它放在请求的Authorization头里(格式:Bearer <你的access-token>),通过API Gateway或者其他方式传给Lambda。 - Lambda中编写验证逻辑:
先确保Lambda的IAM角色有cognito-idp:GetUser的权限,然后用AWS SDK调用API:
const AWS = require('aws-sdk'); const cognito = new AWS.CognitoIdentityServiceProvider({ region: '你的AWS区域' }); exports.handler = async (event) => { // 从请求头中提取Access Token const authHeader = event.headers.Authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return { statusCode: 401, body: JSON.stringify('未提供有效令牌') }; } const accessToken = authHeader.split(' ')[1]; try { // 调用Cognito API验证令牌并获取用户信息 const user = await cognito.getUser({ AccessToken: accessToken }).promise(); // 令牌有效,继续处理业务逻辑 return { statusCode: 200, body: JSON.stringify({ message: '会话有效', username: user.Username }) }; } catch (error) { // 令牌无效(过期、篡改、非法等),返回401 return { statusCode: 401, body: JSON.stringify('会话无效:' + error.message) }; } };
如果令牌无效,这个API会抛出NotAuthorizedException或ExpiredTokenException等明确错误,你可以根据错误类型返回对应提示。
方法二:手动验证JWT令牌(性能更优)
Cognito的ID Token是标准JWT格式,你可以手动验证它的签名、过期时间、受众(Audience)等信息,这种方式不需要调用AWS服务,响应更快,适合高并发场景。
步骤:
- 获取Cognito公钥:Cognito会把公钥放在固定地址:
https://cognito-idp.<你的区域>.amazonaws.com/<你的用户池ID>/.well-known/jwks.json,建议缓存这些公钥,避免每次请求都拉取。 - 用JWT库验证令牌:比如用
jsonwebtoken+jwks-rsa库(需要在Lambda层或打包时包含这些依赖):
const jwt = require('jsonwebtoken'); const jwksClient = require('jwks-rsa'); // 初始化JWKS客户端,用于从Cognito获取公钥 const client = jwksClient({ jwksUri: 'https://cognito-idp.<你的区域>.amazonaws.com/<你的用户池ID>/.well-known/jwks.json' }); // 封装获取公钥的函数 function getSigningKey(header, callback) { client.getSigningKey(header.kid, function(err, key) { const signingKey = key.publicKey || key.rsaPublicKey; callback(null, signingKey); }); } exports.handler = async (event) => { const authHeader = event.headers.Authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return { statusCode: 401, body: JSON.stringify('未提供有效令牌') }; } const idToken = authHeader.split(' ')[1]; return new Promise((resolve, reject) => { jwt.verify(idToken, getSigningKey, { audience: '<你的Cognito客户端ID>', // 必须和Amplify配置的clientId一致 issuer: 'https://cognito-idp.<你的区域>.amazonaws.com/<你的用户池ID>', algorithms: ['RS256'] // Cognito固定用RS256签名 }, function(err, decoded) { if (err) { resolve({ statusCode: 401, body: JSON.stringify('会话无效:' + err.message) }); } else { // 令牌有效,decoded中包含用户的username、邮箱等信息 resolve({ statusCode: 200, body: JSON.stringify({ message: '会话有效', userInfo: decoded }) }); } }); }); };
两种方法对比:
- 方法一:简单易维护,无需处理JWT细节,还能顺便获取用户属性信息,但会调用AWS API,有轻微延迟和极低成本。
- 方法二:性能更好,无额外API调用,但需要处理公钥缓存、JWT验证细节,依赖第三方库。
根据你的业务场景选择就行啦!
内容的提问来源于stack exchange,提问作者KMC
相关产品推荐
相关产品推荐

