我设置了 4 个 CloudFront 分配,它们都具有相同的 S3 源并且都具有查看器协议策略:HTTP 和 HTTPS。它们的区别在于备用域名和限制查看者访问。
- 分布 1:备用域名:无,限制查看者访问:无
- 分布 2:备用域名:无,限制查看者访问:是
- 分发 3:备用域名:distribution3.example.com,限制查看者访问:否
- 分发 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'));