使用 Ionic 2 通过预签名 url 上传到 s3 时出现 SignatureDoesNotMatch 错误
SignatureDoesNotMatch error when uploading to s3 via a pre signed url using Ionic 2
我正在尝试将视频上传到 s3 并有一个预先签名的 PUT url。以下是这样做的代码。
import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
import {MediaCapture} from 'ionic-native';
import {Http} from '@angular/http';
import { Transfer } from 'ionic-native';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public base64Image: string;
constructor(private navController: NavController, public http: Http) {
this.base64Image = "https://placehold.it/150x150";
}
public takeVideo() {
MediaCapture.captureVideo({limit:2}).then(function(videoData){
var link = "https://mysamplebucket.s3.amazonaws.com/non-tp/esx.mov?AWSAccessKeyId=TEMP_KEYY&Expires=1482290587&Signature=JUIHHI%2FcnLkqSVg%3D&x-amz-security-token=FQoDYXDGRfTXk6hma0Rxew6yraAX%2FlYGaQmYLwkvsuuB3%2F%2FtPvGDVs3dIQG0Ty3MeMjn0p%%26djt5xhAMk73pndJbZP0tCYYlvPvlUAyL8x7O%%2B3AwEa%%2B9b43yarIuPLCvujmKLTDyi%%3D%3Di";
var options: any;
options = {
fileKey: 'file',
fileName: 'esx.mov',
httpMethod: 'PUT',
chunkedMode: false,
mimeType: 'video/quicktime',
encodeURI: false,
headers: {
'Content-Type': 'video/quicktime'
}
};
var ft = new Transfer();
ft.upload(videoData[0].fullPath, link, options, false)
.then((result: any) => {
this.success(result);
}).catch((error: any) => {
this.failed(error);
});
}, function(err){
alert(err);
});
}
}
这是生成预签名 PUT url 的代码。
var params = {Bucket: s3_bucket, Key: filename, Expires: 900000};
var url = {
'url' : s3.getSignedUrl('putObject', params)
};
我明白了,SignatureDoesNotMatch
错误。该消息说,The request signature we calculated does not match the signature you provided. Check your key and signing method.
我不确定我在这里做错了什么 - 我查看了其他一些 SO 和 Ionic 问题并尝试了他们推荐的方法但无济于事。关于我做错了什么有什么想法吗?
您的上传 PUT
请求将有一个 Content-Type: video/quicktime
header。
当 Content-Type
header 出现在请求(而不是响应)中时,它的值是 Signature V2 规范请求中的 non-optional 组件...这意味着您必须将其传递给生成签名的代码。
var params = {Bucket: s3_bucket, Key: filename, Expires: 900000};
还需要这个字符串(video/quicktime
,在这种情况下)作为 ContentType: ...
传递给它用于 PUT
请求(但不是 GET
请求,因为这描述了您 发送的内容 ,而 GET
请求通常不发送实际内容。
SDK documentation 似乎没有特别提到这一点,但 S3 绝对需要它。
如果其他人正在看这个并且情况与我相似,当我的 s3 存储桶的 CORS 配置不包含 <AllowedHeader>*</AllowedHeader>
时,我会收到类似的 SignatureDoesNotMatchError
我 运行 从一个存储桶移动到另一个存储桶时,复制除 CORS 配置之外的所有设置。
我们在下载已上传的文件时遇到了这个问题。我们收到预签名 url,但当尝试下载带有该预签名 url 的文件时,它说“签名不匹配”。
我们在向 AWS 报告票证时收到的解决方案,因为所有方法都失败了。场景是我们为 S3 存储桶启用了自定义 AWS KMS 加密,但我们在使用 GeneratePresignedUrlRequest api 时试图连同我们的请求一起发送“kms 密钥”。 AWS 说,我们不必发送 KMS 密钥,而是在不从客户端加密的情况下发送。当我说未加密时,不完全是这样,它已经以加密形式出现,当我们使用“AWSS3V4SignerType”进行签名时,我们将 kms id 作为附加参数发送,这不是开始时所必需的。希望这是有道理的。
AWS 在 header 中寻找的参数是:
- 算法
- 凭证范围
- 签名headers
- 日期
- 到期日期
- 签名
- KMS 密钥 - 我们传递了这个,这不是必需的。
我正在尝试将视频上传到 s3 并有一个预先签名的 PUT url。以下是这样做的代码。
import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
import {MediaCapture} from 'ionic-native';
import {Http} from '@angular/http';
import { Transfer } from 'ionic-native';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public base64Image: string;
constructor(private navController: NavController, public http: Http) {
this.base64Image = "https://placehold.it/150x150";
}
public takeVideo() {
MediaCapture.captureVideo({limit:2}).then(function(videoData){
var link = "https://mysamplebucket.s3.amazonaws.com/non-tp/esx.mov?AWSAccessKeyId=TEMP_KEYY&Expires=1482290587&Signature=JUIHHI%2FcnLkqSVg%3D&x-amz-security-token=FQoDYXDGRfTXk6hma0Rxew6yraAX%2FlYGaQmYLwkvsuuB3%2F%2FtPvGDVs3dIQG0Ty3MeMjn0p%%26djt5xhAMk73pndJbZP0tCYYlvPvlUAyL8x7O%%2B3AwEa%%2B9b43yarIuPLCvujmKLTDyi%%3D%3Di";
var options: any;
options = {
fileKey: 'file',
fileName: 'esx.mov',
httpMethod: 'PUT',
chunkedMode: false,
mimeType: 'video/quicktime',
encodeURI: false,
headers: {
'Content-Type': 'video/quicktime'
}
};
var ft = new Transfer();
ft.upload(videoData[0].fullPath, link, options, false)
.then((result: any) => {
this.success(result);
}).catch((error: any) => {
this.failed(error);
});
}, function(err){
alert(err);
});
}
}
这是生成预签名 PUT url 的代码。
var params = {Bucket: s3_bucket, Key: filename, Expires: 900000};
var url = {
'url' : s3.getSignedUrl('putObject', params)
};
我明白了,SignatureDoesNotMatch
错误。该消息说,The request signature we calculated does not match the signature you provided. Check your key and signing method.
我不确定我在这里做错了什么 - 我查看了其他一些 SO 和 Ionic 问题并尝试了他们推荐的方法但无济于事。关于我做错了什么有什么想法吗?
您的上传 PUT
请求将有一个 Content-Type: video/quicktime
header。
当 Content-Type
header 出现在请求(而不是响应)中时,它的值是 Signature V2 规范请求中的 non-optional 组件...这意味着您必须将其传递给生成签名的代码。
var params = {Bucket: s3_bucket, Key: filename, Expires: 900000};
还需要这个字符串(video/quicktime
,在这种情况下)作为 ContentType: ...
传递给它用于 PUT
请求(但不是 GET
请求,因为这描述了您 发送的内容 ,而 GET
请求通常不发送实际内容。
SDK documentation 似乎没有特别提到这一点,但 S3 绝对需要它。
如果其他人正在看这个并且情况与我相似,当我的 s3 存储桶的 CORS 配置不包含 <AllowedHeader>*</AllowedHeader>
我 运行 从一个存储桶移动到另一个存储桶时,复制除 CORS 配置之外的所有设置。
我们在下载已上传的文件时遇到了这个问题。我们收到预签名 url,但当尝试下载带有该预签名 url 的文件时,它说“签名不匹配”。 我们在向 AWS 报告票证时收到的解决方案,因为所有方法都失败了。场景是我们为 S3 存储桶启用了自定义 AWS KMS 加密,但我们在使用 GeneratePresignedUrlRequest api 时试图连同我们的请求一起发送“kms 密钥”。 AWS 说,我们不必发送 KMS 密钥,而是在不从客户端加密的情况下发送。当我说未加密时,不完全是这样,它已经以加密形式出现,当我们使用“AWSS3V4SignerType”进行签名时,我们将 kms id 作为附加参数发送,这不是开始时所必需的。希望这是有道理的。 AWS 在 header 中寻找的参数是:
- 算法
- 凭证范围
- 签名headers
- 日期
- 到期日期
- 签名
- KMS 密钥 - 我们传递了这个,这不是必需的。