如何限制Cognito用户仅访问自身DynamoDB待办数据?
实现用户仅操作自身待办清单的权限控制方案
1. 改造DynamoDB数据模型,绑定用户身份
- 给所有待办清单、事项记录添加用户唯一标识字段(比如
ownerSub),存储Cognito用户的sub值(这是Cognito为每个用户分配的不可变唯一ID)。 - 推荐优化表结构:将
user#<sub>设为分区键,排序键用list#<listId>(清单)或item#<itemId>(事项),这样天然实现用户数据的物理隔离,查询效率更高,也更容易做权限控制。
2. Lambda层强制校验归属关系
创建操作(清单/事项)
- 从API Gateway传递的授权上下文里获取当前用户的
sub(路径:event.requestContext.authorizer.claims.sub),自动写入DynamoDB记录,禁止前端传入该字段,避免篡改。 - 示例代码片段:
def create_todo_list(event, context): user_sub = event['requestContext']['authorizer']['claims']['sub'] list_data = json.loads(event['body']) # 自动注入用户标识,覆盖前端可能传入的字段 list_data['ownerSub'] = user_sub # 写入DynamoDB dynamodb.put_item(TableName='TodoLists', Item=list_data) return {'statusCode': 201, 'body': json.dumps(list_data)}
读取/更新/删除操作
- 操作时必须同时传入目标清单ID和当前用户的
sub作为查询条件:- 读取:使用
Query或GetItem时,同时指定清单ID和ownerSub = 当前用户sub,无匹配则返回403/404。 - 更新/删除:先查询目标记录的
ownerSub是否与当前用户sub一致,不一致则直接返回403禁止访问,不执行后续操作。
- 读取:使用
- 示例校验逻辑:
def update_todo_list(event, context): user_sub = event['requestContext']['authorizer']['claims']['sub'] list_id = event['pathParameters']['listId'] # 查询目标清单,同时校验归属 response = dynamodb.get_item( TableName='TodoLists', Key={'listId': list_id, 'ownerSub': user_sub} ) if 'Item' not in response: return {'statusCode': 403, 'body': json.dumps({'message': '无权限操作该清单'})} # 执行更新逻辑 update_expression = "SET #name = :name" expression_attribute_names = {"#name": "name"} expression_attribute_values = {":name": json.loads(event['body'])['name']} dynamodb.update_item( TableName='TodoLists', Key={'listId': list_id, 'ownerSub': user_sub}, UpdateExpression=update_expression, ExpressionAttributeNames=expression_attribute_names, ExpressionAttributeValues=expression_attribute_values ) return {'statusCode': 200, 'body': json.dumps({'message': '更新成功'})}
3. IAM权限兜底,限制Lambda访问范围
给Lambda的执行角色添加细粒度DynamoDB权限,确保即使Lambda逻辑出现漏洞,IAM也能阻止越权访问:
- 如果用
user#<sub>作为分区键,可使用dynamodb:LeadingKeys条件键限制:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:Query" ], "Resource": "arn:aws:dynamodb:你的区域:你的账号ID:table/你的待办表名", "Condition": { "StringEquals": { "dynamodb:LeadingKeys": ["${cognito-identity.amazonaws.com:sub}"] } } } ] }
- 如果用
ownerSub作为普通属性,可使用dynamodb:Attributes条件键限制操作时必须包含该属性,且值为当前用户sub。
4. API Gateway层面加固
- 在API的集成请求映射模板中,将Cognito用户的
sub自动注入到Lambda的event参数里,避免前端篡改用户标识。 - 对API路径参数(如
listId)做格式校验,防止恶意请求。
内容的提问来源于stack exchange,提问作者thedeepfield
相关产品推荐
相关产品推荐

