Google云端存储从CDN NPM获得signedUrl

时间:2018-09-20 07:45:02

标签: node.js google-cloud-platform google-cloud-storage pre-signed-url google-cloud-cdn

我正在使用以下代码为我的内容创建一个签名的网址:

var storage = require('@google-cloud/storage')();
var myBucket = storage.bucket('my-bucket');
var file = myBucket.file('my-file');

//-
// Generate a URL that allows temporary access to download your file.
//-
var request = require('request');

var config = {
  action: 'read',
  expires: '03-17-2025'
};

file.getSignedUrl(config, function(err, url) {
  if (err) {
    console.error(err);
    return;
  }

  // The file is now available to read from the URL.

});

这将创建一个以https://storage.googleapis.com/my-bucket/开头的网址

如果我将该URL放在浏览器中,就可以读取。

但是,我想URL是对存储桶文件的直接访问,并且没有通过我配置的CDN。

我看到在文档(https://cloud.google.com/nodejs/docs/reference/storage/1.6.x/File#getSignedUrl)中,您可以传递一个cname选项,该选项将url替换为https://storage.googleapis.com/my-bucket/到我的存储桶CDN。

但是,当我复制生成的URL时,服务帐户或生成的url似乎无权访问该资源。

我已将Firebase管理员服务帐户添加到存储桶中,但仍然无法访问。

此外,从文档中看,CDN签名的URL与通过该API签名的URL似乎有很大不同。是否可以从api创建CDN签名的URL,或者我应该按照https://cloud.google.com/cdn/docs/using-signed-urls?hl=en_US&_ga=2.131493069.-352689337.1519430995#configuring_google_cloud_storage_permissions中的说明手动创建它?

3 个答案:

答案 0 :(得分:0)

对于对该签名的节点代码感兴趣的任何人:

    var url = 'URL of the endpoint served by Cloud CDN';
    var key_name = 'Name of the signing key added to the Google Cloud Storage bucket or service';
    var key = 'Signing key as urlsafe base64 encoded string';
    var expiration = Math.round(new Date().getTime()/1000) + 600; //ten minutes after, in seconds

    var crypto = require("crypto");
    var URLSafeBase64 = require('urlsafe-base64');

    // Decode the URL safe base64 encode key
    var decoded_key = URLSafeBase64.decode(key);

    // buILD URL
    var urlToSign = url 
            + (url.indexOf('?') > -1 ? "&" : "?")
            + "Expires=" + expiration
            + "&KeyName=" + key_name;

    //Sign the url using the key and url safe base64 encode the signature
    var hmac = crypto.createHmac('sha1', decoded_key); 
    var signature = hmac.update(urlToSign).digest();
    var encoded_signature = URLSafeBase64.encode(signature);

    //Concatenate the URL and encoded signature
    urlToSign += "&Signature=" + encoded_signature;

答案 1 :(得分:0)

Cloud CDN内容交付网络可与HTTP(S)负载平衡配合使用,以将内容交付给您的用户。您是否正在使用HTTPS负载平衡器向用户交付内容? 您可以在使用Google Cloud CDN和HTTP(S)负载平衡以及将内容插入缓存中看到此附件文档[1]。

[1] https://cloud.google.com/cdn/docs/overview [2] https://cloud.google.com/cdn/docs/concepts

您得到什么错误代码?您可以使用curl命令并发送带有错误代码的输出以进行进一步分析吗?

由于不是所有HTTP响应都是可缓存的,您是否可以确认所做的配置符合可缓存性的要求? Google Cloud CDN仅缓存那些满足特定条件的响应[3],请确认。确认后,我会做进一步调查并为您提供建议。

[3]可缓存性:https://cloud.google.com/cdn/docs/caching#cacheability

您能否在下面提供这两个命令的输出,这将帮助我验证这些对象是否存在权限问题?这些命令将在对象上转储所有当前的权限设置。

gsutil acl获取gs:// [full_path_to_file_to_be_cached] gsutil ls -L gs:// [full_path_to_file_to_be_cached]

有关权限的更多详细信息,请参阅此GCP文档[4]

[4]设置存储桶权限:https://cloud.google.com/storage/docs/cloud-console#_bucketpermission

否,无法从API创建CDN签名的URL

答案 2 :(得分:0)

来自 Google 文档 here。 @htafoya 提供的答案似乎是合法的。 但是,我花了几个小时来思考为什么签名 URL 不起作用,因为 CDN 端点抱怨访问被拒绝。最终我发现使用 crypto 模块的代码不会产生与 gcloud compute sign-url 计算的相同的 hmac-sha1 哈希值,我仍然不知道为什么。

同时,我看到 this lib (jsSHA) 非常酷,它生成与 gcloud 完全相同的 HMAC-SHA1 哈希值,并且它有一个简洁的 API,所以我认为我应该在这里发表评论,以便如果其他人有同样的挣扎会从中受益,这是我用来签署 gcloud cdn URL 的最终代码:

    import jsSHA from 'jssha';
    const url = `https://{domain}/{path}`;
    const expire = Math.round(new Date().getTime() / 1000) + daySeconds;
  const extendedUrl = `${url}${url.indexOf('?') > -1 ? "&" : "?"}Expires=${expire}&KeyName=${keyName}`;

  // use jssha
  const shaObj = new jsSHA("SHA-1", "TEXT", { hmacKey: { value: signKey, format: "B64" } });
  shaObj.update(extendedUrl);
  const signature = safeSign(shaObj.getHMAC('B64'));
  return `${extendedUrl}&Signature=${signature}`;

工作很棒!