2011-11-15 29 views
6

Tôi đang cố gắng tạo một URL S3 đã ký bằng cách sử dụng Javascript & NodeJS. Tôi đã sử dụng thông số this .Tạo một URL S3 có chữ ký với Javascript

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 

này tạo ra một url tương tự như sau:

https://s3-eu-west-1.amazonaws.com/mybucket/test.txt?AWSAccessKeyId=XXXXXX&Expires=1331290899&Signature=EciGxdQ1uOqgFDCRon4vPqTiCLc%3D 

Tuy nhiên, tôi nhận được lỗi sau khi truy cập vào nó:

SignatureDoesNotMatch 

The request signature we calculated does not match the signature you provided. 
Check your key and signing method. 

Tôi đang làm gì sai khi tạo chữ ký?

EDIT - mưu toan VỚI KNOX

Tôi bây giờ cố gắng sử dụng Knox để tạo ra một URL đã ký kết. Tôi cần phải thêm tiêu đề với yêu cầu bắt buộc tải xuống. Tôi đã chỉnh sửa như sau:

Added amazonHeaders: 'response-content-disposition:attachment', để client.signedUrl- http://jsfiddle.net/BpGNM/1/

Added options.amazonHeaders + '\n' + để auth.queryStringToSign - http://jsfiddle.net/6b8Tm/

Thông điệp mà hiện đang được gửi đến auth.hmacSha1 để tạo ra các sig là:

'GET\n\n\n1321374212\nresponse-content-disposition:attachment\n/meshmesh-dev/test/Readme.md' 

Sau đó tôi đã cố gắng truy cập URL mới của mình bằng số response-content-disposition=attachment được thêm dưới dạng biến var. Tuy nhiên, tôi vẫn nhận được lỗi tương tự đã nêu ở trên.

+0

Có cùng vấn đề với bạn, điều này có bao giờ được giải quyết không? –

Trả lời

8

Tôi sẽ thử sử dụng Knox cùng với Node.Js. Nó được biết đến là một sự kết hợp tuyệt vời và cũng tự sử dụng thư viện Node.js Crypto đó là loại gì bạn đang cố gắng để làm - giúp bạn tiết kiệm thời gian :)

Thông tin thêm ở đây: https://github.com/LearnBoost/knox

Thân, bạn chỉ có thể làm điều gì đó như:

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); 

Edit: bạn cũng có thể nhìn vào Knox và chỉ cần kiểm tra những gì các chức năng signedUrl làm và thực hiện điều đó yourself.Than bạn có thể thêm vào các cuộc gọi auth.signQuery một tùy chọn thêm gọi 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); 
}; 

Shai.

+0

Cảm ơn. Tôi đã sử dụng Knox, nhưng tôi cần phải gửi tiêu đề với yêu cầu ('phản hồi-nội dung-bố trí ': tệp đính kèm') - vì vậy tôi đã cố gắng ký các URL của riêng mình. Bất kỳ ý tưởng làm thế nào điều này được thực hiện với Knox? – Kit

+1

Đã chỉnh sửa câu trả lời của tôi cho bạn –

+1

cảm ơn. Đang thử một số thứ bây giờ ... – Kit

3

có thể một quá nhiều dòng mới?

var stringToSign ='GET\n\n\n' + date + '\n\n' + resource; 

Nếu sự giúp đỡ của bất kỳ ở đây là một rác PHP thực hiện mà chắc chắn hoạt động:

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; 
    } 

}

EDIT--

Có một cái nhìn tại nút này.js s3 tải lên mã, (nó không phải của tôi nhưng thấy nó nằm xung quanh trên mac của tôi - vì vậy nếu bất cứ ai có thể thuộc tính nó cho ai đó cho tôi biết và tôi sẽ làm đạo cụ). Hy vọng rằng điều này có thể giúp (lần thứ 3 may mắn)

https://gist.github.com/1370593

+0

cảm ơn. Tôi sẽ cố gắng và tìm ra những gì các chức năng trên đang làm đúng. Tuy nhiên, ngay cả khi không có thêm '\ n' sau ngày hết hạn - sig vẫn không thành công. – Kit

+0

Xin lỗi một chút ngớ ngẩn của nó và không phải bằng ngôn ngữ phù hợp với bạn nhưng đó là điều đầu tiên tôi phải trao tay - nếu bạn có bất kỳ câu hỏi nào cho tôi biết. –

+0

Một ảnh cuối cùng ... Nếu nhóm có trong tài nguyên .e.g /mybucket/test.txt không chỉ là /text.txt? –

0

thực hiện của tôi sử dụng AWS-SDK và 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(); 
     }); 
    }); 
} 
Các vấn đề liên quan