当前位置: 首页 > 知识库问答 >
问题:

S3从lambda生成的getObject预签名url不工作

栾峰
2023-03-14

我有下面的lambda,它在将文件上传到bucket并将其预签名的URL发送到API时被触发。

import urllib3
import boto3
import json
import urllib

def lambda_handler(event, context):

    headers = {
        'Content-Type': "application/json",
        'Accept': "*/*", 'Accept-Encoding': "gzip,deflate,br",
        'Connection': "keep-alive"
    }

    http = urllib3.PoolManager()

    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(
        event['Records'][0]['s3']['object']['key'], encoding='utf-8')
        
    preSignedUrl = boto3.client('s3').generate_presigned_url(
        ClientMethod='get_object', Params={'Bucket': bucket, 'Key': key}, ExpiresIn=3600)

    params = {
        "url": preSignedUrl,
        "file_name": key.split("/")[-1]
    }
    
    print("Request params: ", params)

    url = "http://abcdefg.io/file"
    
    try:
        r = http.request("POST", url, body=json.dumps(params), headers={
                    'Content-Type': 'application/json'})
        print("Response: ", r.data)
    except Exception as e:
        print(e)  

这是生成预先签名的URL,但我无法使用它访问文件。当我在浏览器中键入URL时,我会得到以下信息:,

<Error>
   <Code>AccessDenied</Code>
   <Message>Access Denied</Message>
   <RequestId>ESAB5DBZCTGX1JEW</RequestId>
 <HostId>C/aB8l0LL3C3ifAzuvcWBz89mTV1MkYHsYGXvlzgLQvVnqEvrea+KCfIbBUUOBSgYJ+PX+2kyh8=</HostId>
</Error>

我尝试使用命令aws s3 presign从cloud shell生成URL

我补充说,

client = boto3.client("s3",region_name=<my-region>, aws_access_key_id=<my_access_key>, aws_secret_access_key=<my_secret_key>) 

并再次生成预签名的URL。新生成的URL也起到了作用。所以问题在于客户。如果没有特别提到钥匙,它就无法工作。我记得在lambda代码中生成预签名URL时没有指定密钥。那么,这里真正的问题是什么?


共有1个答案

从阎宝
2023-03-14

这个问题似乎很可能是由这里上下文中与lambda执行角色附加/关联的策略引起的。因此,对于解决方案,如果您在角色的权限中添加一个内联策略(如下所示),那么lambda应该能够生成工作的预签名URL。如果您使用AWS管理控制台,那么您可以通过lambda函数导航到lambda角色的权限-

内联策略:

{
"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "VisualEditor0",
        "Effect": "Allow",
        "Action": [
            "s3:GetObject",
            "s3:ListBucket"
        ],
        "Resource": "*"
    }
]

}

从lambda(具有适当的权限)生成S3预签名URL的简单版本可能如下所示(在JavaScript中):

var AWS = require('aws-sdk');
var s3 = new AWS.S3({
  signatureVersion: 'v4',
});


exports.handler = (event, context, callback) => {
  const url = s3.getSignedUrl('getObject', {
    Bucket: '<bucket name>',
    Key: '<path to object in bucket>',
    Expires: 1000,
  });


  callback(null, url);
};
 类似资料:
  • 我知道水桶是存在的。当我通过AWS Web GUI导航到此项目并双击它时,它将打开带有URL的对象,并且运行良好: 所以我认为我在使用SDK时肯定做错了什么。

  • 问题内容: 我正在使用NodeJS AWS开发工具包生成预签名的S3 URL。该文档提供了一个生成预签名URL的示例。 这是我的确切代码(省略了敏感信息): 生成的URL如下所示: 我正在将该URL复制到浏览器中,并得到以下响应: 我知道水桶存在。当我通过AWS Web GUI导航至该项目并双击时,它会打开带有URL的对象,并且工作正常: 因此,我被认为是我使用SDK的方式一定做错了。 问题答案:

  • 如果你想把自己的资源发放给第三方用户访问,但是又不想开放Bucket的读权限,可以通过生成预签名URL的形式提供给用户一个临时的访问URL。在生成URL时,你可以指定URL过期的时间,从而限制用户长时间访问。 生成一个预签名的URL 如下代码: String bucketName = "your-bucket-name"; String key = "your-object-key"; // 设

  • 如果你想把自己的资源发放给第三方用户访问,但是又不想开放Bucket的读权限,可以通过生成预签名URL的形式提供给用户一个临时的访问URL。在生成URL时,你可以指定URL过期的时间,从而限制用户长时间访问。 生成预签名URL来获取Object <?php $url = $client->generatePresignedUrl(array( 'Bucket' => 'your-buck

  • 标题说明一切。这是我的代码; 我使用节点强大的文件。 成功上传后,url变量返回s3 url,类似以下内容; 下面是我的参数 我错过了什么?

  • 我尝试使用helloworld.html为我的S3 Bucket手动创建CloudFront预签名URL(不使用OAI),如下文所示 https://docs.aws.amazon.com/amazonCloudFront/latest/developerguide/privateContent.html。 null 我怀疑CloudFront在S3上丢失了IAM策略。我尝试了S3的完全公共访问,