【问题标题】:The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256不支持您提供的授权机制。请使用 AWS4-HMAC-SHA256
【发布时间】:2014-12-19 10:12:37
【问题描述】:

当我尝试将文件上传到新法兰克福地区的 S3 存储桶时,我收到错误 AWS::S3::Errors::InvalidRequest The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.。在US Standard 区域中一切正常。

脚本:

backup_file = '/media/db-backup_for_dev/2014-10-23_02-00-07/slave_dump.sql.gz'
s3 = AWS::S3.new(
    access_key_id:     AMAZONS3['access_key_id'],
    secret_access_key: AMAZONS3['secret_access_key']
)

s3_bucket = s3.buckets['test-frankfurt']

# Folder and file name
s3_name = "database-backups-last20days/#{File.basename(File.dirname(backup_file))}_#{File.basename(backup_file)}"

file_obj = s3_bucket.objects[s3_name]
file_obj.write(file: backup_file)

aws-sdk (1.56.0)

如何解决?

谢谢。

【问题讨论】:

标签: ruby amazon-web-services amazon-s3 aws-sdk


【解决方案1】:

AWS4-HMAC-SHA256,也称为签名版本 4,(“V4”)是 S3 支持的两种身份验证方案之一。

所有区域都支持 V4,但美国标准¹,以及许多(但不是全部)其他区域也支持其他较旧的方案,签名版本 2(“V2”)。

根据http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html ... 2014 年 1 月之后部署的新 S3 区域将仅支持 V4。

由于法兰克福于 2014 年底推出,它不支持 V2,这就是此错误表明您正在使用的版本。

http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingAWSSDK.html 解释了如何在各种 SDK 中启用 V4,假设您使用的是具有该功能的 SDK。

我推测某些旧版本的 SDK 可能不支持此选项,因此如果上述方法没有帮助,您可能需要更新版本的 SDK。


¹US Standard 是基于 us-east-1 区域的 S3 区域部署的旧名称。自从最初编写此答案以来, "Amazon S3 renamed the US Standard Region to the US East (N. Virginia) Region to be consistent with AWS regional naming conventions." 出于所有实际目的,这只是命名的变化。

【讨论】:

  • 这难倒了 Fedora 20 附带的 s3cmd-1.5.0-0.alpha3.fc20.noarch。显然还有 stumps 1.5.0-rc1,目前是最新的。
  • @DavidTonhofer 似乎是对的。看起来 s3cmd 开发人员还没有实现 AWS4-HMAC-SHA256github.com/s3tools/s3cmd/issues/402
  • @"Michael - sqlbot" 我现在切换到“awscli”。对于那些赶时间的人:yum install python-pip;点安装 awscli; aws配置; aws --region=eu-central-1 s3 ls s3://$BUCKET 等...
  • aws-sdk v2 似乎很好地支持 AWS4-HMAC-SHA256 "V4" 身份验证(相关issue
  • thnx.. 这对我很有用
【解决方案2】:

用节点,试试

var s3 = new AWS.S3( {
    endpoint: 's3-eu-central-1.amazonaws.com',
    signatureVersion: 'v4',
    region: 'eu-central-1'
} );

【讨论】:

    【解决方案3】:

    您应该在config 中设置signatureVersion: 'v4' 以使用新的签名版本:

    AWS.config.update({
        signatureVersion: 'v4'
    });
    

    适用于JS sdk。

    【讨论】:

    • 拯救了我的一天!不知道为什么这个选项没有得到更多的宣传
    【解决方案4】:

    对于使用boto3 (Python SDK) 的人,请使用以下代码

    from botocore.client import Config
    
    
    s3 = boto3.resource(
        's3',
        aws_access_key_id='xxxxxx',
        aws_secret_access_key='xxxxxx',
        config=Config(signature_version='s3v4')
    )
    

    【讨论】:

    • 我收到错误AuthorizationQueryParametersErrorError parsing the X-Amz-Credential parameter; the region 'us-east-1' is wrong; expecting 'us-east-2'us-east-2 所以我在上面的代码中添加了region_name='us-east-2'
    【解决方案5】:

    我一直在使用 Django,我不得不添加这些额外的配置变量来完成这项工作。 (除了https://simpleisbetterthancomplex.com/tutorial/2017/08/01/how-to-setup-amazon-s3-in-a-django-project.html中提到的设置)。

    AWS_S3_REGION_NAME = "ap-south-1"
    

    或boto3 1.4.4之前的版本:

    AWS_S3_REGION_NAME = "ap-south-1"
    
    AWS_S3_SIGNATURE_VERSION = "s3v4"
    

    【讨论】:

    • 对于使用 boto 的人来说仍然是最佳答案,谢谢
    • 正是我需要的
    【解决方案6】:

    PHP SDK 的类似问题,这可行:

    $s3Client = S3Client::factory(array('key'=>YOUR_AWS_KEY, 'secret'=>YOUR_AWS_SECRET, 'signature' => 'v4', 'region'=>'eu-central-1'));
    

    重要的是signatureregion

    【讨论】:

    • 是否需要指定区域?
    【解决方案7】:
    AWS_S3_REGION_NAME = "ap-south-1"
    
    AWS_S3_SIGNATURE_VERSION = "s3v4"
    

    这也节省了我冲浪 24 小时后的时间..

    【讨论】:

    • 这很好用,如果不是“ap-south-1”,您只需更改区域名称以适合您的名称
    • 无需更改编码!设置这两个环境变量,boto 就可以正常工作了
    【解决方案8】:

    Flask 代码 (boto3)

    别忘了导入配置。另外,如果您有自己的配置类,请更改其名称。

    from botocore.client import Config
    
    s3 = boto3.client('s3',config=Config(signature_version='s3v4'),region_name=app.config["AWS_REGION"],aws_access_key_id=app.config['AWS_ACCESS_KEY'], aws_secret_access_key=app.config['AWS_SECRET_KEY'])
    s3.upload_fileobj(file,app.config["AWS_BUCKET_NAME"],file.filename)
    url = s3.generate_presigned_url('get_object', Params = {'Bucket':app.config["AWS_BUCKET_NAME"] , 'Key': file.filename}, ExpiresIn = 10000)
    

    【讨论】:

      【解决方案9】:

      在 Java 中我必须设置一个属性

      System.setProperty(SDKGlobalConfiguration.ENFORCE_S3_SIGV4_SYSTEM_PROPERTY, "true")
      

      并将区域添加到 s3Client 实例。

      s3Client.setRegion(Region.getRegion(Regions.EU_CENTRAL_1))
      

      【讨论】:

        【解决方案10】:

        使用boto3,代码如下:

        s3_client = boto3.resource('s3', region_name='eu-central-1')
        

        s3_client = boto3.client('s3', region_name='eu-central-1')
        

        【讨论】:

        • 你有两次 s3_client 吗?
        【解决方案11】:

        对于使用 boto 配置的 thumbor-aws,我需要将其放入 $AWS_CONFIG_FILE

        [default]
        aws_access_key_id = (your ID)
        aws_secret_access_key = (your secret key)
        s3 =
            signature_version = s3
        

        所以任何直接使用boto而不做任何更改的东西,这可能会有用

        【讨论】:

          【解决方案12】:

          对于 Android SDK,setEndpoint 解决了这个问题,尽管它已被弃用。

          CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
                          context, "identityPoolId", Regions.US_EAST_1);
          AmazonS3 s3 = new AmazonS3Client(credentialsProvider);
          s3.setEndpoint("s3.us-east-2.amazonaws.com");
          

          【讨论】:

            【解决方案13】:

            基本上这个错误是因为我使用的是旧版本的 aws-sdk 并且我更新了版本所以发生了这个错误。

            在我使用节点 js 的情况下,我在 parmas 对象中使用 signatureVersion,如下所示:

            const AWS_S3 = new AWS.S3({
              params: {
                Bucket: process.env.AWS_S3_BUCKET,
                signatureVersion: 'v4',
                region: process.env.AWS_S3_REGION
              }
            });
            

            然后我将签名从 params 对象中取出并像魅力一样工作:

            const AWS_S3 = new AWS.S3({
              params: {
                Bucket: process.env.AWS_S3_BUCKET,
                region: process.env.AWS_S3_REGION
              },
              signatureVersion: 'v4'
            });
            

            【讨论】:

              【解决方案14】:

              检查您的 AWS S3 存储桶区域并在连接请求中传递正确的区域。

              在我的 Senario 中,我为 亚太地区(孟买) 设置了 'APSouth1'

              using (var client = new AmazonS3Client(awsAccessKeyId, awsSecretAccessKey, RegionEndpoint.APSouth1))
              {
                  GetPreSignedUrlRequest request1 = new GetPreSignedUrlRequest
                  {
                      BucketName = bucketName,
                      Key = keyName,
                      Expires = DateTime.Now.AddMinutes(50),
                  };
                  urlString = client.GetPreSignedURL(request1);
              }
              

              【讨论】:

                【解决方案15】:

                对于 Boto3 ,请使用此代码。

                import boto3
                from botocore.client import Config
                
                
                s3 = boto3.resource('s3',
                        aws_access_key_id='xxxxxx',
                        aws_secret_access_key='xxxxxx',
                        region_name='us-south-1',
                        config=Config(signature_version='s3v4')
                        )
                

                【讨论】:

                  【解决方案16】:

                  在我的例子中,请求类型是错误的。我正在使用 GET(dumb) 它必须是 PUT。

                  【讨论】:

                  • 节省了我的一天,就我而言,我使用的是 POST。
                  【解决方案17】:

                  django/boto3/django-storages 的 Supernova 答案与我合作:

                  AWS_S3_REGION_NAME = "ap-south-1"

                  或boto3 1.4.4之前的版本:

                  AWS_S3_REGION_NAME = "ap-south-1"

                  AWS_S3_SIGNATURE_VERSION = "s3v4"

                  只需将它们添加到您的 settings.py 并相应地更改区域代码

                  您可以从以下位置检查 aws 区域: enter link description here

                  【讨论】:

                    【解决方案18】:

                    这是我在 Python 中使用的函数

                    def uploadFileToS3(filePath, s3FileName):
                        s3 = boto3.client('s3', 
                                        endpoint_url=settings.BUCKET_ENDPOINT_URL,
                                        aws_access_key_id=settings.BUCKET_ACCESS_KEY_ID,
                                        aws_secret_access_key=settings.BUCKET_SECRET_KEY,
                                        region_name=settings.BUCKET_REGION_NAME
                                        )
                        try:
                            s3.upload_file(
                                filePath, 
                                settings.BUCKET_NAME, 
                                s3FileName
                                )
                    
                            # remove file from local to free up space
                            os.remove(filePath)
                    
                            return True
                        except Exception as e:
                            logger.error('uploadFileToS3@Error')
                            logger.error(e)
                            return False
                    

                    【讨论】:

                      【解决方案19】:

                      有时默认版本不会更新。添加此命令

                      AWS_S3_SIGNATURE_VERSION = "s3v4"
                      

                      settings.py

                      【讨论】:

                        【解决方案20】:

                        试试这个组合。

                        const s3 = new AWS.S3({
                          endpoint: 's3-ap-south-1.amazonaws.com',       // Bucket region
                          accessKeyId: 'A-----------------U',
                          secretAccessKey: 'k------ja----------------soGp',
                          Bucket: 'bucket_name',
                          useAccelerateEndpoint: true,
                          signatureVersion: 'v4',
                          region: 'ap-south-1'             // Bucket region
                        });
                        

                        【讨论】:

                          【解决方案21】:

                          我被困了 3 天,终于,在阅读了大量博客和答案后,我能够配置 Amazon AWS S3 Bucket。

                          在 AWS 方面

                          我假设你已经

                          1. 创建了一个 s3 存储桶
                          2. 在 IAM 中创建了一个用户

                          步骤

                          1. 配置 CORS 设置

                            你的存储桶 > 权限 > CORS 配置

                            <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
                            <CORSRule>
                                <AllowedOrigin>*</AllowedOrigin>
                                <AllowedMethod>GET</AllowedMethod>
                                <AllowedMethod>POST</AllowedMethod>
                                <AllowedMethod>PUT</AllowedMethod>
                                <AllowedHeader>*</AllowedHeader>
                            </CORSRule>
                            </CORSConfiguration>```
                            
                            
                          2. 生成存储桶策略

                          您的存储桶 > 权限 > 存储桶策略

                          应该和这个差不多

                           {
                               "Version": "2012-10-17",
                               "Id": "Policy1602480700663",
                               "Statement": [
                                   {
                                       "Sid": "Stmt1602480694902",
                                       "Effect": "Allow",
                                       "Principal": "*",
                                       "Action": "s3:GetObject",
                                       "Resource": "arn:aws:s3:::harshit-portfolio-bucket/*"
                                   }
                               ]
                           }
                          
                          PS: Bucket policy should say `public` after this 
                          
                          1. 配置访问控制列表

                          您的存储桶 > 权限 > 访问控制列表

                          提供公共访问权限

                          PS:访问控制列表后面应该写public

                          1. 取消阻止公共访问

                          您的存储桶 > 权限 > 阻止公共访问

                          编辑并关闭所有选项

                          **如果您正在使用 django,请注意 将以下行添加到您项目的 settings.py 文件中 **

                          #S3 BUCKETS CONFIG
                          
                          AWS_ACCESS_KEY_ID = '****not to be shared*****'
                          AWS_SECRET_ACCESS_KEY = '*****not to be shared******'
                          AWS_STORAGE_BUCKET_NAME = 'your-bucket-name'
                          
                          AWS_S3_FILE_OVERWRITE = False
                          AWS_DEFAULT_ACL = None
                          DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
                          
                          # look for files first in aws 
                          STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
                          
                          # In India these settings work
                          AWS_S3_REGION_NAME = "ap-south-1"
                          AWS_S3_SIGNATURE_VERSION = "s3v4"
                          
                          

                          【讨论】:

                            【解决方案22】:

                            完整的 nodejs 版本:

                            const AWS = require('aws-sdk');
                            
                            var s3 = new AWS.S3( {
                                endpoint: 's3.eu-west-2.amazonaws.com',
                                signatureVersion: 'v4',
                                region: 'eu-west-2'
                            } );
                            
                            
                            const getPreSignedUrl = async () => {
                                const params = {
                                    Bucket: 'some-bucket-name/some-folder',
                                    Key: 'some-filename.json',
                                    Expires: 60 * 60 * 24 * 7
                                };
                                try {
                                    const presignedUrl = await new Promise((resolve, reject) => {
                                        s3.getSignedUrl('getObject', params, (err, url) => {
                                            err ? reject(err) : resolve(url);
                                        });
                                    });
                                    console.log(presignedUrl);
                                } catch (err) {
                                    if (err) {
                                        console.log(err);
                                    }
                                }
                            };
                            
                            getPreSignedUrl();
                            

                            【讨论】:

                              猜你喜欢
                              • 2017-12-06
                              • 2016-06-15
                              相关资源
                              最近更新 更多