概览

暴露私有内容的 Web 应用程序需要实施访问控制机制,确保只有获得授权的用户才能访问内容。示例包括需要用户身份验证的基于 SPA 的内部门户,以及下载机密文件。根据使用案例,可以在源级别或在 CDN 级别实现访问控制。

常见使用案例

基于源的授权

如果您使用 CloudFront 作为未启用缓存的反向代理(即在托管缓存策略中配置了禁用缓存),则可以简单地使用源(例如,API Gateway)的原生授权功能。为了使其正常工作,请将源请求策略配置为将包含授权信息的请求属性(例如,授权标头)转发到您的源。

如果您的内容可缓存,但您更愿意继续在自己的基础设施上管理授权,请考虑使用 Lambda@Edge 集成 CloudFront 与您的授权服务器。此架构可使您从 CloudFront 缓存中受益。在本博客中阅读有关此实现的更多信息。

如果您想将授权逻辑从 Web 应用程序组件转移到 CloudFront,请考虑以下部分。

使用签名令牌的基于 CloudFront 的授权

CloudFront 使用签名 URL 或签名 Cookie 提供原生授权机制。要使用此方法,请按照文档中说明的步骤操作:

  • 使用签名密钥组配置用于对令牌进行签名的非对称加密密钥。
  • 在身份验证工作流程中,将所需的令牌字段附加到所售资源网址的查询参数或 Cookie 中。令牌包含到期日期、签名密钥 ID、策略和签名。该策略允许您定义通过 CloudFront 令牌验证测试的请求需要满足的条件。例如,您可以使用自定义策略生成对以特定路径开头的所有网址有效的令牌。
  • 在用于私有内容的 CloudFront 缓存行为中启用签名。从那时起,所有请求都将由 CloudFront 控制以进行令牌验证。未经授权的请求会收到 403 错误,这可以使用 CloudFront 的自定义错误页面功能进行自定义。

使用 aws-sdk 通过您的私钥生成有效令牌。举例来说,Nodejs 中的以下代码为特定对象 edge-image.jpg 生成一个 CloudFront 签名 URL,有效期为两小时。

const AWS = require('aws-sdk');

// It's recommended not to store signing keys in code. The below is just an illustrative example.
const cloudfrontAccessKeyId = 'K25ULYFPSTHQP9';
const cloudFrontPrivateKey = '-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQ....2gvvIH\n-----END RSA PRIVATE KEY-----';

const signer = new AWS.CloudFront.Signer(cloudfrontAccessKeyId, cloudFrontPrivateKey);
const signedUrl = signer.getSignedUrl({
  url: 'https://d3jqlnxofenq2x.cloudfront.net/edge-image.jpg',
  expires: Math.floor((Date.now() + 2 * 60 * 60 * 1000) / 1000),
});
console.log(signedUrl);

上面的代码段的输出如下所示:

https://d3jqlnxofenq2x.cloudfront.net/edge-image.jpg?Expires=1660317158&Key-Pair-Id=K25ULYFP9THQP9&Signature=agW2XF9S5AW0YCc6c7pkCwccJmxaIAWFO~uXn9KtOXtz4JTY7eRF07opJiseGXJxzlMeD4V6FUH8I-gOH~Gvafa16RFV9IryxCyzL9mIYt-XbDKMrY0ONzTWUk2x16AKDK27VoUwEPiI9dpPXMp7f4MsrpKA-u6huZCsulh0~aAYN~x25uNoDO-WgZpfkKFeKc910u4PVnEaKLlZlpuJ0hqWUjMVPes9DfA~msToJeyjrVzLi2R8O8LuuYHsAMAHXr7E9qB8tAoDWz24CurCirxc6sB45Zc-oK9JigX0L4~F~F1TE9i39ysmQF4UrOyu0bp7MKGSDBwLE1P2C3gWNw__

使用 CloudFront Functions 的基于 CloudFront 的授权

如果 CloudFront 的原生签名令牌不符合您的授权要求,则可以使用边缘函数构建自定义授权逻辑。例如,您可能希望使用不同的密码术对令牌进行签名,例如对称加密,或者您可能希望在签名中包含非标准属性,例如用户代理标头,或者您可能想要实现基于用户网络的条件令牌化逻辑。下面的自定义实现演示了边缘函数的一些可能性:

  • CloudFront Functions 验证基于 JWT 的令牌。请注意,CloudFront Functions 目前不允许外部网络调用,因此,需要将签名密钥存储在函数代码中。为了降低在 CloudFront 函数代码中存储签名密钥的风险,切勿在代码中手动配置密钥,而应在部署到 CloudFront 之前使用自动轮换密钥并生成函数代码。这样,密钥就不会存在上传到 Github 等公共存储库的风险。
  • AWS 解决方案:边缘的安全媒体交付。此 AWS 解决方案使用 CloudFront 函数来实现适用于视频流的自定义授权机制。
  • 使用 OpenID Connect 对托管在 S3 上的单页应用程序进行身份验证。这些解决方案使用 AWS Secrets Manager 存储签名密钥,并且可与 Cognito 或 Okta 等外部身份提供者(IdP)配合使用。此实现在 CloudFront Functions 推出之前发布,这就是它完全依赖 Lambda@Edge 的原因。它可以进行优化,以在授权部分使用 CloudFront Functions,而将 Lambda@Edge 用于与 IdP 集成。

资源

此页内容对您是否有帮助?