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

通过IAM策略管控S3对象访问异常:修改策略后仍可上传文件

问题排查与解决方法

看起来你遇到的核心问题是Lambda执行时没有使用Cognito用户的身份权限,而是默认使用了Lambda自身的执行角色权限,导致你修改Cognito关联的IAM策略后,权限管控没有生效。下面分点分析原因和解决步骤:

一、核心原因:Lambda使用自身执行角色而非用户Cognito身份

你的代码中直接调用s3.putObject时,默认会使用Lambda的执行角色(不是Cognito认证角色)去访问S3。如果这个Lambda执行角色本身就拥有S3的上传权限(比如AmazonS3FullAccess或者针对性的PutObject权限),那么不管你怎么修改Cognito关联的IAM策略,用户都能成功上传文件——因为实际生效的是Lambda执行角色的权限。

二、解决步骤

1. 改用用户的Cognito身份获取临时凭证调用S3

你需要通过用户的AccessToken,从Cognito Identity Pool获取该用户对应的临时AWS凭证,然后用这些凭证初始化S3客户端,再执行上传操作。修改后的代码示例如下:

const AWS = require('aws-sdk');
const cognitoidentity = new AWS.CognitoIdentity();

app.post("/api/upload/add", upload.single('uploadedFile'), async(req, res) => {
  try {
    const token = getAccessToken(req.headers.authorization);
    const decodedToken = jwt_decode(token);
    const sub = decodedToken.sub;
    // 注意:如果解码的token里没有identityId,需先调用GetId API获取
    const identityId = decodedToken.identity_id;

    // 1. 获取用户的临时AWS凭证
    const credParams = {
      IdentityId: identityId,
      Logins: {
        'cognito-idp.eu-west-1.amazonaws.com/<你的用户池ID>': token // 替换为你的用户池ID
      }
    };
    const creds = await cognitoidentity.getCredentialsForIdentity(credParams).promise();

    // 2. 使用临时凭证初始化S3客户端
    const s3 = new AWS.S3({
      accessKeyId: creds.Credentials.AccessKeyId,
      secretAccessKey: creds.Credentials.SecretKey,
      sessionToken: creds.Credentials.SessionToken
    });

    // 3. 执行上传操作
    const params = {
      Bucket: '<Bucket name>', 
      Key: `${sub}/${req.body.propertyId}/${req.file.originalname}`, 
      Body: req.file.buffer, 
      ACL: 'private'
    };
    const data = await s3.putObject(params).promise();
    res.status(200).send(data);
  } catch (err) {
    console.log("error====", err);
    res.status(500).send(err.message);
  }
});

2. 确保Lambda执行角色拥有获取凭证的权限

需要给Lambda的执行角色添加允许调用cognito-identity:GetCredentialsForIdentity的权限,否则Lambda无法获取用户的临时凭证。可以在IAM控制台给Lambda角色添加如下内联策略:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "cognito-identity:GetCredentialsForIdentity",
      "Resource": "*"
    }
  ]
}

3. 验证IAM策略的正确性(可选)

确认你的Cognito认证角色策略中的路径匹配正确:

  • 你的上传路径是${sub}/xxx/xxx,策略中的Resourcearn:aws:s3:::<Bucket name>/${cognito-identity.amazonaws.com:sub}/*正好匹配该路径,这部分是没问题的。
  • 策略中的cognito-identity.amazonaws.com:sub变量会在Cognito角色策略中自动替换为用户的sub值,无需手动修改。

4. 处理IAM策略缓存(可选)

IAM策略修改后可能会有5分钟左右的缓存,如果修改后立即测试可能没生效,可以等待几分钟后再验证。

三、额外建议

  • 遵循最小权限原则:Lambda执行角色只保留必要的权限(比如获取Cognito凭证的权限),不要给它S3的直接操作权限,确保所有S3操作都通过用户的Cognito身份权限管控。
  • 可以使用AWS IAM Access Analyzer来检查策略的有效性,确认权限是否符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 02:57:29