0

我设置了 4 个 CloudFront 分配,它们都具有相同的 S3 源并且都具有查看器协议策略:HTTP 和 HTTPS。它们的区别在于备用域名和限制查看者访问。

  1. 分布 1:备用域名:,限制查看者访问:
  2. 分布 2:备用域名:,限制查看者访问:
  3. 分发 3:备用域名:distribution3.example.com,限制查看者访问:
  4. 分发 4:备用域名:distribution4.example.com,限制查看者访问:

我将图像上传到 S3 存储桶(对其的访问被阻止)并尝试使用 CloudFront 分配访问它。签署 URL 时,我使用相同的到期值(一周内),在相同的受信任密钥组中使用相同的公钥,并使用相同的代码(使用固定策略)对所有 URL 进行签名。我的域已在 Cloudflare 注册,其 HTTPS 证书是 AWS Certificate Manager 中的 Amazon Issue。以下是结果:

分布 1:备用域名:,限制查看者访问:

http://distribution1.cloudfront.net/image.jpg -> 200 OK
https://distribution1.cloudfront.net/image.jpg -> 200 OK

分布 2:备用域名:,限制查看者访问:

http://distribution2.cloudfront.net/image.jpg -> 403 Forbidden
https://distribution2.cloudfront.net/image.jpg -> 403 Forbidden
http://distribution2.cloudfront.net/image.jpg?Expires=XXX&Signature=XXX&Key-Pair-Id=XXX -> 200 OK
https://distribution2.cloudfront.net/image.jpg?Expires=XXX&Signature=XXX&Key-Pair-Id=XXX -> 200 OK

分发 3:备用域名:distribution3.example.com,限制查看者访问:

http://distribution3.cloudfront.net/image.jpg -> 200 OK
https://distribution3.cloudfront.net/image.jpg -> 200 OK
http://distribution3.example.com/image.jpg -> 200 OK
https://distribution3.example.com/image.jpg -> 200 OK

分发 4:备用域名:distribution4.example.com,限制查看者访问:

http://distribution4.cloudfront.net/image.jpg -> 403 Forbidden
https://distribution4.cloudfront.net/image.jpg -> 403 Forbidden
http://distribution4.example.com/image.jpg -> 403 Forbidden
https://distribution4.example.com/image.jpg -> 403 Forbidden
http://distribution4.cloudfront.net/image.jpg?Expires=XXX&Signature=XXX&Key-Pair-Id=XXX -> 200 OK
https://distribution4.cloudfront.net/image.jpg?Expires=XXX&Signature=XXX&Key-Pair-Id=XXX -> 200 OK
http://distribution4.example.com/image.jpg?Expires=XXX&Signature=XXX&Key-Pair-Id=XXX -> 200 OK
https://distribution4.example.com/image.jpg?Expires=XXX&Signature=XXX&Key-Pair-Id=XXX -> 403 -> Access denied XML page. WHY?

为什么最后一个案例失败了?我错过了什么吗?

用于生成签名 URL 的 nodejs 代码对所有人都是相同的:

fs = require('fs')
crypto = require('crypto')

const EXPIRES = 1624235093   // Mon Jun 21 2021 00:24:53 GMT+0000
const KEY_PAIR_ID = 'KUXXX'  // Cloudfront -> Key management -> Public keys
const privateKey = fs.readFileSync('private_key.pem', 'utf8')

// Creating a signed URL using a canned policy
// https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-canned-policy.html
function createSignedURL(baseURL) {
  // canned policy
  const cannedPolicy = {
    "Statement": [
      {
        "Resource": baseURL,
        "Condition": {
          "DateLessThan": {
            "AWS:EpochTime": EXPIRES
          }
        }
      }
    ]
  }

  // Remove white space (including tabs and newline characters) from the policy string
  const cannedPolicyString = JSON.stringify(cannedPolicy).replace(/[\s\t\n\r]/g, '')  
  // console.log(cannedPolicyString);

  // Sign policy with private key using RSA-SHA1, 
  // Base64-encode the string, 
  // Remove white space (including tabs and newline characters) from the hashed and signed string
  // Replace characters that are invalid in a URL query string with characters that are valid.
  const sign = crypto.createSign('RSA-SHA1')
  sign.update(cannedPolicyString)
  sign.end()
  const signature = sign.sign(privateKey, 'base64').replace(/\+/g, '-').replace(/=/g, '_').replace(/\//g, '~')
  // console.log(signature);

  // Creating a signed URL
  const signedURL = `${ baseURL }?Expires=${ EXPIRES }&Signature=${ signature }&Key-Pair-Id=${ KEY_PAIR_ID }`
  // console.log(signedURL);

  // return
  return signedURL
}

console.log(createSignedURL('https://distribution4.example.com/image.jpg'));
4

0 回答 0