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

如何在Serverless框架中通过JWT动态设置dynamodb:LeadingKeys条件

解决方案:在Serverless项目中用JWT的sub动态设置DynamoDB LeadingKeys条件

问题根源

你之前的写法无效,核心原因是:

  • Serverless.yml中定义的IAM策略是静态部署的,${event.requestContext.authorizer.jwt.claims.sub}是Lambda运行时的变量,无法在部署阶段解析到IAM策略中。
  • cognito-identity.amazonaws.com:sub仅适用于Cognito身份池(联合身份认证场景),而你用的是API Gateway JWT授权器,这个变量不会被填充。

方案一:代码级细粒度控制(推荐,简单直接)

放弃在IAM策略中动态绑定sub,转而在Lambda代码里强制执行分区键匹配逻辑:

  1. 给Lambda的IAM角色授予DynamoDB表的基础CRUD权限(无需LeadingKeys条件)
  2. 在Lambda函数中从JWT声明中提取sub,然后在所有DynamoDB操作中强制限制分区键为该sub值

Serverless.yml权限配置示例

iamRoleStatements:
  - Effect: Allow
    Action:
      - dynamodb:GetItem
      - dynamodb:PutItem
      - dynamodb:UpdateItem
      - dynamodb:DeleteItem
      - dynamodb:Query
    Resource: "arn:aws:dynamodb:${self:provider.region}:${aws:accountId}:table/${self:custom.tableName}"

Node.js Lambda代码示例

const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();

exports.handler = async (event) => {
  // 从JWT声明中获取用户sub
  const userSub = event.requestContext.authorizer.jwt.claims.sub;
  const tableName = process.env.TABLE_NAME;

  // 示例:查询用户自己的数据
  const queryParams = {
    TableName: tableName,
    KeyConditionExpression: 'pk = :userSub', // pk是你的分区键字段名
    ExpressionAttributeValues: { ':userSub': userSub }
  };

  try {
    const result = await dynamodb.query(queryParams).promise();
    return { statusCode: 200, body: JSON.stringify(result.Items) };
  } catch (err) {
    return { statusCode: 500, body: JSON.stringify(err) };
  }
};

方案二:IAM策略结合API Gateway上下文传递(严格权限控制)

如果需要在IAM层面实现强制控制,确保即使代码出现漏洞也无法越权,可通过以下步骤实现:

  1. 配置JWT授权器传递sub到上下文
    • 若使用Cognito用户池作为JWT授权器:API Gateway会自动将JWT的sub填充到event.requestContext.identity.sub
    • 若使用自定义JWT授权器:在授权器的响应中添加context.sub = claims.sub,将sub注入到请求上下文
  2. 在IAM策略中引用AWS预定义变量
    使用aws:userid变量(对应Cognito用户池的sub)绑定LeadingKeys:

Serverless.yml权限配置示例(Cognito用户池场景)

iamRoleStatements:
  - Effect: Allow
    Action:
      - dynamodb:GetItem
      - dynamodb:PutItem
      - dynamodb:UpdateItem
      - dynamodb:DeleteItem
      - dynamodb:Query
    Resource: "arn:aws:dynamodb:${self:provider.region}:${aws:accountId}:table/${self:custom.tableName}"
    Condition:
      StringEqualsIgnoreCaseIfExists:
        dynamodb:LeadingKeys: "${aws:userid}"

最佳实践

  • 优先选择方案一:实现成本低,调试方便,且能灵活处理复杂业务逻辑
  • 若采用方案二:确保JWT授权器正确传递sub到IAM可识别的上下文变量,避免权限遗漏
  • 始终验证JWT的有效性:API Gateway的JWT授权器已做基础验证,但可在Lambda中二次校验sub的合法性
  • 统一分区键命名:将分区键固定为类似userSub的字段,确保所有操作都基于该字段做权限限制

内容的提问来源于stack exchange,提问作者Rumira Daksith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 00:01:00