Google Cloud Storage 从 CDN npm 获取signedUrl

问题描述 投票:0回答:4

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

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 签名的 URL 有很大不同。 是否可以从 api 创建 CDN 签名网址,或者我应该按照以下说明手动创建它: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
4个回答
2
投票

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

    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;

0
投票

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 get gs://[要缓存的文件的完整路径] gsutil ls -L gs://[要缓存的文件的完整路径]

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

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

不,无法从 API 创建 CDN 签名 URL


0
投票

来自 Google 文档此处。 @htafoya 提供的答案似乎是合法的。 然而,我花了几个小时来思考为什么签名 URL 无法工作,因为 CDN 端点抱怨访问被拒绝。最终我发现使用

crypto
模块的代码不会产生与
gcloud compute sign-url
计算的相同的 hmac-sha1 哈希值,我仍然不知道为什么。

同时,我看到这个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}`;

工作得很好!


0
投票

稍微修改了@htafoya代码,

async generateSignedUrlForCdnResource(fileName: string): Promise<string> {
    const url =
      this.configService.get<string>(GCP_BACKEND_BUCKET_BASE_URL) + fileName;
    const base64SignedKey = this.configService.get<string>(
      GCP_SIGNING_BASE_64_ENCODED_KEY,
    );
    const expirationTime = Date.now() + 2 * 60; // 2 minutes
    const strippedUrl = url.trim();

    const parsedUrl = new URL(strippedUrl);
    const queryParams = new URLSearchParams(parsedUrl.search);

    const expirationTimestamp = Math.floor(expirationTime);

    const decodedKey = Buffer.from(base64SignedKey, 'base64url');

    const urlToSign = `${strippedUrl}${queryParams.toString() ? '&' : '?'}Expires=${expirationTimestamp}&KeyName=${this.configService.get<string>(GCP_SIGNING_KEY_FILE_NAME)}`;

    const hmac = crypto.createHmac('sha1', decodedKey);
    hmac.update(urlToSign);
    const digest = hmac.digest();
    const signature = Buffer.from(digest).toString('base64url');

    return `${urlToSign}&Signature=${signature}`;
  }
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.