NS-Vue/Rails 对 S3 存储桶的预签名 PUT 请求给出 403
NS-Vue/Rails Presigned PUT request to S3 bucket giving 403
我的前端是一个 Nativescript-Vue 应用程序。后端是 Rails。我从 rrails 服务器得到一个预先签名的 url 并使用它在客户端发送一个放置请求来上传图像。我像这样在 rails 上生成了预签名的 url,遵循 this:
def create_presigned_url
filename = "#{self.id}.jpg"
Aws.config[:credentials]=Aws::Credentials.new(
"secret_id",
"secret_key")
s3 = Aws::S3::Resource.new(region: 'ap-southeast-1')
bucket = 'bucket_name'
obj = s3.bucket(bucket).object(filename)
self.presigned_url = obj.presigned_url(:put, { acl: 'public-read' })
self.update_column(:image_url, obj.public_url)
end
长话短说,上面的代码生成了一个预签名的 url,我使用它在客户端使用 NativeScript-background-http 插件执行放置请求:
var session = bghttp.session("image-upload");
UploadFile(session, file, url) {
var request = {
url: url,
method: "PUT",
headers: {
"Content-Type": "application/octet-stream"
},
description: `Uploading ${file.substr(file.lastIndexOf("/") + 1)}`
};
var task = session.uploadFile(file, request);
}
图片上传正常,显示:
LOG from device Nexus 6P: 'currentBytes: 4096'
LOG from device Nexus 6P: 'totalBytes: 622121'
LOG from device Nexus 6P: 'eventName: progress'
LOG from device Nexus 6P: 'currentBytes: 323584'
LOG from device Nexus 6P: 'totalBytes: 622121'
LOG from device Nexus 6P: 'eventName: progress'
LOG from device Nexus 6P: 'currentBytes: 606208'
LOG from device Nexus 6P: 'eventName: progress'
LOG from device Nexus 6P: 'totalBytes: 622121'
LOG from device Nexus 6P: 'currentBytes: 622121'
LOG from device Nexus 6P: 'totalBytes: 622121'
LOG from device Nexus 6P: 'eventName: progress'
LOG from device Nexus 6P: 'eventName: error'
LOG from device Nexus 6P: 'eventName: 403'
LOG from device Nexus 6P: 'eventName: {}'
出现 403 错误,响应为:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
...
我用谷歌搜索了这个错误,发现 SO 上的所有响应都是关于拥有不正确的 AWS 密钥的,但是,我已经确保我在 rails 上拥有正确的 AWS 凭证。我怀疑在生成预签名 url 时它可能与内容类型有关,但我不确定。我的存储桶权限似乎是正确的,但我可能在那里错过了一些东西。我已经设置了策略和 CORS。
这是存储桶策略:
{
"Version": "2012-10-17",
"Id": "my-policy-id",
"Statement": [
{
"Sid": "my-sid",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::my-id:user/my-user"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
这是 CORS:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<ExposeHeader>ETag</ExposeHeader>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
我的 IAM 用户也有必要的策略。
如有任何见解,我们将不胜感激。
编辑: 我什至删除了存储桶策略并授予对存储桶的所有 public 访问权限,但我仍然看到 403 错误。错误是 一个。
我不得不将 self.presigned_url = obj.presigned_url(:put, { acl: 'public-read' })
更改为 self.presigned_url = obj.presigned_url(:put, expires_in: 10*60, content_type: 'application/octet-stream')
和每个人的存储桶 ACL Public 列表,私有写入。存储桶策略
{
"Version": "2012-10-17",
"Id": "policy_id",
"Statement": [
{
"Sid": "my_statement_id",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::user_id:user/iam_user"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my_bucket/*"
},
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::my_bucket/*"
}
]
}
我的前端是一个 Nativescript-Vue 应用程序。后端是 Rails。我从 rrails 服务器得到一个预先签名的 url 并使用它在客户端发送一个放置请求来上传图像。我像这样在 rails 上生成了预签名的 url,遵循 this:
def create_presigned_url
filename = "#{self.id}.jpg"
Aws.config[:credentials]=Aws::Credentials.new(
"secret_id",
"secret_key")
s3 = Aws::S3::Resource.new(region: 'ap-southeast-1')
bucket = 'bucket_name'
obj = s3.bucket(bucket).object(filename)
self.presigned_url = obj.presigned_url(:put, { acl: 'public-read' })
self.update_column(:image_url, obj.public_url)
end
长话短说,上面的代码生成了一个预签名的 url,我使用它在客户端使用 NativeScript-background-http 插件执行放置请求:
var session = bghttp.session("image-upload");
UploadFile(session, file, url) {
var request = {
url: url,
method: "PUT",
headers: {
"Content-Type": "application/octet-stream"
},
description: `Uploading ${file.substr(file.lastIndexOf("/") + 1)}`
};
var task = session.uploadFile(file, request);
}
图片上传正常,显示:
LOG from device Nexus 6P: 'currentBytes: 4096'
LOG from device Nexus 6P: 'totalBytes: 622121'
LOG from device Nexus 6P: 'eventName: progress'
LOG from device Nexus 6P: 'currentBytes: 323584'
LOG from device Nexus 6P: 'totalBytes: 622121'
LOG from device Nexus 6P: 'eventName: progress'
LOG from device Nexus 6P: 'currentBytes: 606208'
LOG from device Nexus 6P: 'eventName: progress'
LOG from device Nexus 6P: 'totalBytes: 622121'
LOG from device Nexus 6P: 'currentBytes: 622121'
LOG from device Nexus 6P: 'totalBytes: 622121'
LOG from device Nexus 6P: 'eventName: progress'
LOG from device Nexus 6P: 'eventName: error'
LOG from device Nexus 6P: 'eventName: 403'
LOG from device Nexus 6P: 'eventName: {}'
出现 403 错误,响应为:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
...
我用谷歌搜索了这个错误,发现 SO 上的所有响应都是关于拥有不正确的 AWS 密钥的,但是,我已经确保我在 rails 上拥有正确的 AWS 凭证。我怀疑在生成预签名 url 时它可能与内容类型有关,但我不确定。我的存储桶权限似乎是正确的,但我可能在那里错过了一些东西。我已经设置了策略和 CORS。
这是存储桶策略:
{
"Version": "2012-10-17",
"Id": "my-policy-id",
"Statement": [
{
"Sid": "my-sid",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::my-id:user/my-user"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
这是 CORS:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<ExposeHeader>ETag</ExposeHeader>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
我的 IAM 用户也有必要的策略。
如有任何见解,我们将不胜感激。
编辑: 我什至删除了存储桶策略并授予对存储桶的所有 public 访问权限,但我仍然看到 403 错误。错误是
我不得不将 self.presigned_url = obj.presigned_url(:put, { acl: 'public-read' })
更改为 self.presigned_url = obj.presigned_url(:put, expires_in: 10*60, content_type: 'application/octet-stream')
和每个人的存储桶 ACL Public 列表,私有写入。存储桶策略
{
"Version": "2012-10-17",
"Id": "policy_id",
"Statement": [
{
"Sid": "my_statement_id",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::user_id:user/iam_user"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my_bucket/*"
},
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::my_bucket/*"
}
]
}