如何在Lambda代码中使用AWS自定义授权器权限?能否生成DynamoDB细粒度访问策略?
一、怎么在Lambda代码里用自定义授权器的权限信息?
首先得明确:自定义授权器返回的IAM策略主要是给API Gateway看的——用来决定要不要把请求放行到你的GraphQLAPI Lambda函数。但如果你想在Lambda内部拿到授权器判断出的用户权限、身份信息这些,完全可以通过Lambda的event对象获取。
看你的Serverless配置,用的是type: request类型的授权器,这种情况下API Gateway会把授权器返回的context字段原封不动塞进Lambda的输入event里。举个例子,要是你的授权器代码返回这样的结构:
return { principalId: 'user_123', policyDocument: { Version: '2012-10-17', Statement: [{ Action: 'execute-api:Invoke', Effect: 'Allow', Resource: event.methodArn // 允许访问当前请求的API路径 }] }, context: { userId: 'user_123', allowedDynamoActions: ['get', 'put'], tenantId: 'tenant_456' } };
那在你的GraphQLAPI Lambda里,就能这么取到这些信息:
exports.apiHandler = async (event) => { // 从event里扒出授权器传过来的上下文 const authInfo = event.requestContext.authorizer; const currentUserId = authInfo.userId; const allowedActions = authInfo.allowedDynamoActions; // 接下来就可以根据这些信息做权限校验了 if (allowedActions.includes('get')) { // 执行DynamoDB查询操作 } else { // 返回权限不足的错误 return { statusCode: 403, body: JSON.stringify({ message: '无访问权限' }) }; } // 其他业务逻辑... };
要是想让Lambda能访问DynamoDB,别忘了给Lambda的执行角色加上对应的DynamoDB权限(比如dynamodb:GetItem),然后在Lambda内部用授权器传的上下文做细粒度控制(比如只让用户看自己的数据)。
二、自定义授权器能不能生成DynamoDB细粒度访问的策略?
必须可以!不过这里要分两种场景来说:
场景1:让Lambda用临时权限访问DynamoDB
如果你想让Lambda以用户的身份访问DynamoDB(完全遵循授权器的决策),可以在授权器里调用AWS STS的AssumeRole接口,生成一个带细粒度DynamoDB权限的临时IAM凭证,然后把这些凭证放到context里传给Lambda。之后Lambda就用这个临时凭证去访问DynamoDB,这样DynamoDB的访问就会被临时角色的策略限制住。
不过这种方式需要额外处理STS调用和凭证有效期,复杂度稍高,适合对权限控制要求极高的场景。
场景2:授权器传权限上下文,Lambda内部做校验
这是更常用的做法:授权器只负责验证用户身份,把用户的权限范围(比如允许访问的DynamoDB数据ID、允许的操作类型)放到context里传给Lambda,然后Lambda在执行DynamoDB操作前,根据这些信息做细粒度校验。
比如你的DynamoDB表有个userId字段,授权器把用户的userId传过来,那Lambda查询的时候就可以这么写:
const params = { TableName: 'YourTable', Key: { itemId: requestItemId, userId: authInfo.userId // 确保用户只能访问自己的数据 } }; await dynamodb.getItem(params).promise();
这种方式简单易维护,大部分场景都够用。
对你的Serverless配置的小提醒
你的配置已经正确把授权器和GraphQLAPI绑定了,resultTtlInSeconds: 0表示不缓存授权结果,适合权限经常变化的场景。记得你的APIAuthorizer函数返回的policyDocument要正确允许(或拒绝)访问/api路径的POST请求,不然API Gateway会直接把请求拦下来哦。
内容的提问来源于stack exchange,提问作者Aneil Mallavarapu

