AWS签名和Javascript

时间:2018-03-09 10:28:40

标签: javascript algorithm amazon-web-services amazon-ec2 rhino

我需要通过Javascript向带有签名请求的AWS发送HTTP请求。遗憾的是,我不能将AWS SDK JS用作Node.js或浏览器,但我需要从Rhino JS环境中运行它。 似乎我做了一些非常错误的事情,因为我得到了同样的结果 - AWS无法验证提供的访问凭据。  :(

我使用的代码与Amazons使用的代码相同(但在Python中)。我只使用一个外部lib,所以我可以使用HMCA和SHA。 任何帮助都非常感谢(并且因为我现在挣扎了好几天......),所以是的 - 帮助!

谢谢你提前! 欢呼声,

Joro

gs.include('jshashes');

var method = 'GET';
var service = 'ec2';
var host = 'ec2.amazonaws.com';
var region = 'us-east-1';
var endpoint = 'https://ec2.amazonaws.com';
var access_key = 'ACCESSKEY';
var secret_key = 'SECRET/KEY';
var request_parameters = 'AWSAccessKeyId' + access_key + 'Action=RunInstances&&ImageId=ami-b770fbd8';

function getSignatureKey(key, date, region, service){
  var newKey = "AWS4" + key;
  var kDate = new Hashes.SHA256().b64_hmac(newKey, date); 
  var kRegion = new Hashes.SHA256().b64_hmac(kDate, region); 
  var kService = new Hashes.SHA256().b64_hmac(kRegion, service); 
  var kSigning = new Hashes.SHA256().b64_hmac(kService, "aws4_request"); 

  return kSigning;
}

var gdt = new GlideDateTime();
var datestamp = gdt.getDate().getByFormat('yyyyMMdd') + 'T' + 
gdt.getTime().getByFormat('HHmmss') + 'Z';
var amzdate = gdt.getDate().getByFormat('yyyyMMdd')+"";

var canonical_uri = '/'; 

var canonical_querystring = request_parameters;

var canonical_headers = 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n'
var signed_headers = 'host;x-amz-date';

var payload_hash = new Hashes.SHA256().hex(""); 

var canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash;

var algorithm = 'AWS4-HMAC-SHA256';
var credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request';
var string_to_sign = algorithm + '\n' +  amzdate + '\n' +  credential_scope + '\n' +  new Hashes.SHA256().hex(canonical_request);

var signing_key = getSignatureKey(secret_key, datestamp, region, service);
//Python
//var signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()
var signature = new Hashes.SHA256().hex_hmac(signing_key, string_to_sign);

var authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' +  'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature

var headers = {'x-amz-date':amzdate, 'Authorization':authorization_header}

var request_url = endpoint + '?' + canonical_querystring

var httpRequest = new GlideHTTPRequest(request_url);
httpRequest.setRequestHeader(headers);
var res = httpRequest.get();
gs.print(res.statusCode);
gs.print(res.allHeaders);
gs.print(res.body);

1 个答案:

答案 0 :(得分:1)

检查网址构造。例如,request_parameters有一些缺失和错位的分隔符。

var request_parameters = 'AWSAccessKeyId=' + access_key +
                         '&Action=RunInstances&ImageId=ami-b770fbd8';

除了检查和测试生成的URL之外,您还可以尝试简单的语法,以便更容易检查和更新。仅作为示例,以下

var credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request';
var string_to_sign = algorithm + '\n' +  amzdate + '\n' + credential_scope + '\n' + new Hashes.SHA256().hex(canonical_request);

可以写成如下(这对我来说更容易检查):

var credential_scope = [
    datestamp,
    region,
    service,
    'aws4_request'
].join('/');

var string_to_sign = [
    algorithm,
    amzdate,
    credential_scope,
    new Hashes.SHA256().hex(canonical_request)
].join('\n');