当我尝试将文件上传到新法兰克福地区的 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)
如何解决?
谢谢你。
AWS4-HMAC-SHA256,也称为签名版本 4,(“V4”)是 S3 支持的两种身份验证方案之一。
所有区域都支持 V4,但 US-Standard¹ 和许多(但不是全部)其他区域也支持另一个较旧的方案,签名版本 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."出于所有实际目的,这只是命名的更改。
使用节点,尝试
var s3 = new AWS.S3( {
endpoint: 's3-eu-central-1.amazonaws.com',
signatureVersion: 'v4',
region: 'eu-central-1'
} );
您应该在 config
中设置 signatureVersion: 'v4'
以使用新的签名版本:
AWS.config.update({
signatureVersion: 'v4'
});
适用于 JS
sdk。
对于使用 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'
我一直在使用 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"
PHP SDK的类似问题,这有效:
$s3Client = S3Client::factory(array('key'=>YOUR_AWS_KEY, 'secret'=>YOUR_AWS_SECRET, 'signature' => 'v4', 'region'=>'eu-central-1'));
重要的是 signature
和 region
AWS_S3_REGION_NAME = "ap-south-1"
AWS_S3_SIGNATURE_VERSION = "s3v4"
这也节省了我冲浪 24 小时后的时间。
烧瓶代码 (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)
在Java中我必须设置一个属性
System.setProperty(SDKGlobalConfiguration.ENFORCE_S3_SIGV4_SYSTEM_PROPERTY, "true")
并将区域添加到 s3Client 实例。
s3Client.setRegion(Region.getRegion(Regions.EU_CENTRAL_1))
使用boto3,这是代码:
s3_client = boto3.resource('s3', region_name='eu-central-1')
或者
s3_client = boto3.client('s3', region_name='eu-central-1')
对于使用 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而不做任何改变的东西,这可能很有用
django/boto3/django-storages 的超新星答案和我一起工作:
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
对于 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");
基本上这个错误是因为我使用的是旧版本的 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'
});
检查您的 AWS S3 存储桶区域并在连接请求中传递正确的区域。
在 My 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);
}
就我而言,请求类型是错误的。我正在使用 GET(dumb) 它必须是 PUT。
这是我在 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
有时默认版本不会更新。添加此命令
AWS_S3_SIGNATURE_VERSION = "s3v4"
在settings.py
对于 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')
)
试试这个组合。
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
});
我被困了 3 天,最后,在阅读了大量博客和答案后,我能够配置 Amazon AWS S3 Bucket。
在 AWS 方面
我假设你已经
创建了一个 s3-bucket 在 IAM 中创建了一个用户
脚步
配置您存储的 CORS 设置 > 权限 > CORS 配置
您的存储桶 > 权限 > 存储桶策略
应该和这个类似
{
"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
配置访问控制列表
您的存储桶 > 权限 > 访问控制列表
公开访问
PS:访问控制列表应在此之后显示public
取消阻止公共访问
您的存储桶 > 权限 > 阻止公共访问
编辑并关闭所有选项
**附带说明,如果您正在使用 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"
对我来说,这是解决方案:
AWS_S3_REGION_NAME = "eu-central-1"
AWS_S3_ADDRESSING_STYLE = 'virtual'
这需要添加到你的 Django 项目中的 settings.py
完整的工作 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();
不定期副业成功案例分享
AWS4-HMAC-SHA256
:github.com/s3tools/s3cmd/issues/402