【问题标题】:Google Cloud Storage get signedUrl from CDN npmGoogle Cloud Storage 从 CDN npm 获取 signedUrl
【发布时间】:2018-09-20 07:45:01
【问题描述】:

我正在使用如下代码为我的内容创建签名 URL:

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 放在浏览器中,它是可读的。

但是,我猜该 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 签名的有很大不同。是否可以从 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

【问题讨论】:

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


    【解决方案1】:

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

        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;
    

    【讨论】:

      【解决方案2】:

      Cloud CDN 内容交付网络与 HTTP(S) 负载平衡一起使用,向您的用户交付内容。您是否使用 HTTPS 负载均衡器向您的用户提供内容? 您可以查看此附件文档[1],了解如何使用 Google Cloud CDN 和 HTTP(S) 负载平衡并将内容插入缓存。

      [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

      【讨论】:

        【解决方案3】:

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

        同时,我看到this lib (jsSHA) 很酷,它生成的 HMAC-SHA1 哈希值与gcloud 完全相同,并且它有一个简洁的 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}`;
        

        工作得很好!

        【讨论】:

          猜你喜欢
          • 2018-10-31
          • 1970-01-01
          • 2013-08-22
          • 2015-03-29
          • 2019-12-24
          • 2019-04-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多