[英]Creating a signed S3 URL with Javascript
我正在尝试使用Javascript和NodeJS创建签名的S3 URL。 我使用过这个规范。
var crypto = require('crypto'),
date = 1331290899,
resource = '/myfile.txt',
awskey = "XXXX",
awssecret = "XXXX";
var stringToSign ='GET\n\n\n' + date + '\n\n' + resource;
var sig = encodeURIComponent(crypto.createHmac('sha1', awssecret).update(stringToSign ).digest('base64'));
var url = "https://s3-eu-west-1.amazonaws.com/mybucket" +
resource + "?AWSAccessKeyId=" + awskey + "&Expires="+ date +
"&Signature="+ sig
这会创建一个类似于此的URL:
https://s3-eu-west-1.amazonaws.com/mybucket/test.txt?AWSAccessKeyId=XXXXXX&Expires=1331290899&Signature=EciGxdQ1uOqgFDCRon4vPqTiCLc%3D
但是,访问它时收到以下错误:
SignatureDoesNotMatch
The request signature we calculated does not match the signature you provided.
Check your key and signing method.
创建签名时我做错了什么?
编辑 - 与诺克斯一起尝试
我现在正在尝试使用Knox生成签名的URL。 我需要添加带有强制下载请求的标头。 我编辑了以下内容:
添加了amazonHeaders: 'response-content-disposition:attachment',
到client.signedUrl- http://jsfiddle.net/BpGNM/1/
添加options.amazonHeaders + '\\n' +
到auth.queryStringToSign
- http://jsfiddle.net/6b8Tm/
现在发送到auth.hmacSha1
以创建sig的消息是:
'GET\n\n\n1321374212\nresponse-content-disposition:attachment\n/meshmesh-dev/test/Readme.md'
然后我尝试使用添加为GET var的response-content-disposition=attachment
来访问我的新URL。 但是,我仍然收到上述相同的错误。
我会尝试使用Knox和Node.Js。 它已知是一个伟大的组合,也本身利用Node.JS加密库,这是你正在尝试做的一种 - 节省你的时间:)
更多信息: https : //github.com/LearnBoost/knox
比,你可以做一些像:
var knox = require('knox');
var s3Client = knox.createClient({
key: 'XXX',
secret: 'XXX',
bucket: 'XXX'
});
var expires = new Date();
expires.setMinutes(expires.getMinutes() + 30);
var url = s3Client.signedUrl(filename, expires);
编辑:您也可以查看Knox并查看signedUrl函数的功能并自行实现。您可以在auth.signQuery
调用中添加一个名为amazonHeaders
的额外选项:
Client.prototype.signedUrl = function(filename, expiration){
var epoch = Math.floor(expiration.getTime()/1000);
var signature = auth.signQuery({
amazonHeaders: 'response-content-disposition:attachment',
secret: this.secret,
date: epoch,
resource: '/' + this.bucket + url.parse(filename).pathname
});
return this.url(filename) +
'?Expires=' + epoch +
'&AWSAccessKeyId=' + this.key +
'&Signature=' + encodeURIComponent(signature);
};
夏嘉曦。
也许有太多新行?
var stringToSign ='GET\n\n\n' + date + '\n\n' + resource;
如果它的任何帮助是垃圾PHP实现肯定有效:
class myS3Helper{
public function getSignedImageLink($timeout = 1800)
{
$now = new Zend_Date(); //Gives us a time object that is set to NOW
$now->setTimezone('UTC'); //Set to UTC a-la AWS requirements
$now->addSecond($timeout);
$expirationTime = $now->getTimestamp(); //returns unix timestamp representation of the time.
$signature = urlencode(
base64_encode(
hash_hmac(
'sha1', $this->_generateStringToSign($expirationTime),
$my_aws_secretkey,
true
)
)
);
//FIXME make this less ugly when I know it works
$url = 'https://';
$url .= Zend_Service_Amazon_S3::S3_ENDPOINT; //e.g s3.amazonaws.com
$url .= $this->_getImagePath(); //e.g /mybucket/myFirstCar.jpg
$url .='?AWSAccessKeyId=' . $my_aws_key;
$url .='&Signature=' . $signature; //signature as returned by below function
$url .='&Expires=' . $expirationTime;
return $url;
}
protected function _generateStringToSign($expires)
{
$string = "GET\n"; //Methods
$string .= "\n";
$string .= "\n";
$string .= "$expires\n"; //Expires
$string .= $this->_getImagePath();
return $string;
}
}
编辑 -
看看这个node.js s3上传代码,(它不是我的,但发现它躺在我的Mac上 - 所以如果有人可以将它归于某人让我知道,我会做道具)。 希望这可能会有所帮助(第3次幸运)
我使用AWS-SDK和Rx实现。
import AWS from "aws-sdk"
import Rx from 'rx'
/*
* Credentials could be loaded from env variables
* http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-environment.html
* */
const s3 = new AWS.S3({apiVersion: '2006-03-01'});
export function getS3SignedImage(objectKey) {
return Rx.Observable.create(function (observer) {
s3.getSignedUrl('getObject',{
Bucket: process.env.AWS_BUCKET,
Key: objectKey
}, (err, data) => {
if (err) {
return observer.onError(err);
}
observer.onNext(data);
observer.onCompleted();
});
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.