基于Cognito实现DynamoDB表行级细粒度访问控制问题排查
解决Cognito关联自定义UserID实现DynamoDB行级访问控制的问题
核心问题是你没把Cognito User Pool的自定义UserID正确传递到Identity Pool的临时凭证会话中,导致IAM策略里的条件无法匹配。按以下步骤修正:
1. 确认User Pool用户属性配置
- 确保你的User Pool用户确实有自定义属性(比如
custom:user_id),且值为AA-AA-AA-AA。 - 进入User Pool的App client settings,在Attribute read and write permissions中,允许读取该自定义属性;如果用OAuth流,要在Allowed OAuth scopes里勾选
profile或自定义的scope(确保包含该属性的读取权限)。
2. 配置Identity Pool的属性映射
- 打开Identity Pool的控制台,进入Authentication providers -> 你的Cognito User Pool条目。
- 开启Attribute mapping,点击Add mapping:
- 选择User Pool attribute为你的自定义UserID(比如
custom:user_id); - 选择Identity Pool attribute为
PrincipalTag,并设置Tag键(比如user_id)。
- 选择User Pool attribute为你的自定义UserID(比如
- 保存后,用户通过User Pool认证时,Identity Pool会把这个自定义UserID作为会话标签(Principal Tag)附加到临时IAM凭证上。
3. 修正IAM角色的权限策略
把Cognito_Role的权限策略里的条件改为引用${aws:PrincipalTag/user_id},而不是cognito-identity.amazonaws.com:sub。同时注意区分Query和GetItem的条件:
dynamodb:LeadingKeys用于Query/Scan操作(匹配分区键);dynamodb:Keys用于GetItem/PutItem等操作(明确指定主键值)。
示例策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:Query", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem" ], "Resource": "arn:aws:dynamodb:[REGION]:[ACCOUNT]:table/MyUsers", "Condition": { "StringEquals": { "dynamodb:LeadingKeys": "${aws:PrincipalTag/user_id}", "dynamodb:Keys/UserID": "${aws:PrincipalTag/user_id}" } } } ] }
4. C++ SDK端的注意事项
确保你在获取临时凭证时,是用Cognito User Pool返回的ID Token去请求Identity Pool的凭证:
- 用
CognitoIdentityProviderClient调用AdminInitiateAuth或InitiateAuth获取ID Token; - 用
CognitoIdentityClient调用GetId(传入User Pool的ID Token)获取身份ID; - 再调用
GetCredentialsForIdentity获取临时凭证,之后用该凭证初始化DynamoDB客户端。
排查验证点
- 用
aws sts get-caller-identity --profile your-temp-profile查看临时凭证的标签,确认user_id标签是否存在且值正确; - 检查IAM策略的资源ARN是否和DynamoDB表的ARN完全匹配;
- 确保Identity Pool的信任策略正确,允许Cognito身份服务扮演该角色:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "cognito-identity.amazonaws.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "cognito-identity.amazonaws.com:aud": "[YOUR_IDENTITY_POOL_ID]" }, "ForAnyValue:StringLike": { "cognito-identity.amazonaws.com:amr": "authenticated" } } } ] }
内容的提问来源于stack exchange,提问作者Liam
相关产品推荐
相关产品推荐

