获取 HTTP/1.1 403 禁止访问使用 cloudfront 和私有密钥访问存储在 S3(静态 Web 托管)中的



我收到来自 AWS CloudFront 的以下响应,来自 Java 应用程序,我正在尝试使用签名的 cookie 访问私有内容(网页)。

HTTP/1.1 403 禁止 [内容类型: application/xml, 传输编码: 分块, 连接: 保持活动, 日期: 星期五, 23 Aug 2019 12:47:53 GMT, 服务器: AmazonS3, X-Cache: 来自 cloudfront 的错误, 通过: 1.1 1b964435*************d975cdd***.cloudfront.net (CloudFront), X-amz-cf-pop: MXP64-C1, X-amz-Cf-Id: 6Waw****_ukbfaev1nrJZZYBl******t66R9ctZ*****A==] org.apache.http.conn.BasicManagedEntity@5fdba6f9

我尝试了以下步骤:

  1. 我已经将S3配置为"静态网站托管">
  2. 将存储桶策略设置为 :
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E1J***SIQ****"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-xxxxx-s3-bucket/*"
}
]
}
    存储桶
  1. 的 CORS 配置为:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
  1. 使用以下命令创建 CloudFront 分配:

    • 源设置->源域名:my-s3-存储桶名称
    • 源设置 -> 限制存储桶访问:是
    • 限制查看者访问(使用签名 URL 或签名 Cookie):是。
    • 受信任的签名者:自我(选中)。
    • 将其余属性保留为默认值。
  2. 在(CloudFront 密钥对)下创建安全凭证并下载私有密钥。 使用以下命令将 .pem 文件转换为 .der。

openssl pkcs8 -topk8 -nocrypt -in origin.pem -inform PEM -out new.der -outform DER 
  1. 创建了一个具有以下依赖项的 Maven 项目:
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.327</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.java.dev.jets3t/jets3t -->
<dependency>
<groupId>net.java.dev.jets3t</groupId>
<artifactId>jets3t</artifactId>
<version>0.9.4</version>
</dependency>
  1. 代码如下,尝试使用签名的cookie访问"index.html"文件(保存在S3根目录中):
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.spec.InvalidKeySpecException;
import java.text.ParseException;
import java.util.Date;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.jets3t.service.CloudFrontServiceException;
import com.amazonaws.services.cloudfront.CloudFrontCookieSigner;
import com.amazonaws.services.cloudfront.CloudFrontCookieSigner.CookiesForCustomPolicy;
import com.amazonaws.services.cloudfront.util.SignerUtils;
import com.amazonaws.services.cloudfront.util.SignerUtils.Protocol;
import com.amazonaws.util.DateUtils;
public class SignedCookies {
public static void withCustom() throws InvalidKeySpecException, IOException{
Protocol protocol = Protocol.http;
String resourcePath = "index.html";
String distributionDomain = "***ju***lu***.cloudfront.net";
String privateKeyFilePath = "my-path/pk-APKA####K3WH####7U##.der";
File privateKeyFile = new File(privateKeyFilePath);
String s3ObjectKey = "index.html";
String keyPairId = "APKA####K3WH####7U##";

Date activeFrom = DateUtils.parseISO8601Date("2018-11-14T22:20:00.000Z");
Date expiresOn = DateUtils.parseISO8601Date("2020-11-14T22:20:00.000Z");
String ipRange = null;
CookiesForCustomPolicy cookies = CloudFrontCookieSigner.getCookiesForCustomPolicy(
protocol, distributionDomain, privateKeyFile, s3ObjectKey,
keyPairId, expiresOn, activeFrom, ipRange);

@SuppressWarnings({ "resource", "deprecation" })
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(
SignerUtils.generateResourcePath(protocol, distributionDomain,
resourcePath));
httpGet.addHeader("Cookie", "Secure");
httpGet.addHeader("Cookie", cookies.getPolicy().getKey() + "=" +
cookies.getPolicy().getValue());
httpGet.addHeader("Cookie", cookies.getSignature().getKey() + "=" +
cookies.getSignature().getValue());
httpGet.addHeader("Cookie", cookies.getKeyPairId().getKey() + "=" +
cookies.getKeyPairId().getValue());

HttpResponse response = client.execute(httpGet);
System.out.println(response.toString());
}
public static void main(String[] args) throws FileNotFoundException, IOException, CloudFrontServiceException, ParseException, InvalidKeySpecException {
withCustom();
}
}
  1. 我收到了 403 的回复。

如何解决此问题?

请先阅读我第一篇文章下的最后一条评论。 这部分与上一篇文章有关。 这是我用来使用 signUrlCanned 对 URL 进行签名并获取内容的代码示例,但是当我尝试使用 buildPolicyForSignedUrl 时,访问被拒绝错误。

@JamesDean:感谢您的评论。在上面的例子中。我选择 下拉列表中的源域名(作为 s3 存储桶)并使用了 OAI 我使用 S3 的地方被配置为静态网站,这是我的第一个 错误。无论如何,我通过提供自定义源名称来解决此问题 (静态网站终结点 URL)。然后在未启用"使用 签名的 URL 或签名的 Cookie",并且没有任何问题。但是如果我 启用"使用签名 URL 或签名 Cookie"并尝试使用签名 URL 或签名的cookie收到我无法解决的403错误。我是 如果您无论如何都能帮助我,请在下面提供代码示例。

使用以下代码,我获得了正确的签名 url 并可以访问内容:

byte[] derPrivateKey = EncryptionUtil.convertRsaPemToDer(new FileInputStream(privateKeyFilePath));
//      Generate a "canned" signed URL to allow access to a specific distribution and object
String signedUrlCanned = CloudFrontService.signUrlCanned(
"https://" + distributionDomain + "/" + s3ObjectKey, // Resource URL or Path
keyPairId,     // Certificate identifier, an active trusted signer for the distribution
derPrivateKey, // DER Private key data
ServiceUtils.parseIso8601Date("2020-08-30T22:20:00.000Z") // DateLessThan
);
System.out.println(signedUrlCanned);

另一方面,当我尝试使用根目录中相同 s3 内容(索引.html的自定义策略访问内容时,访问被拒绝:

String policyResourcePath = distributionDomain + "/*" ;
//      Convert an RSA PEM private key file to DER bytes
byte[] derPrivateKey = EncryptionUtil.convertRsaPemToDer(new FileInputStream(privateKeyFilePath));
String policy = CloudFrontService.buildPolicyForSignedUrl(
policyResourcePath, // Resource path (optional, may include '*' and '?' wildcards)
ServiceUtils.parseIso8601Date("2020-11-14T22:20:00.000Z"), // DateLessThan
"0.0.0.0/0", // CIDR IP address restriction (optional, 0.0.0.0/0 means everyone)
ServiceUtils.parseIso8601Date("2017-10-16T06:31:56.000Z")  // DateGreaterThan (optional)
);
String signedUrl = CloudFrontService.signUrl(
"https://" + distributionDomain + "/" + s3ObjectKey, // Resource URL or Path
keyPairId,     // Certificate identifier, an active trusted signer for the distribution
derPrivateKey, // DER Private key data
policy // Access control policy
);
System.out.println(signedUrl);

我收到的回复:


<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AccessDenied</Code>
<Message>Access denied</Message>
</Error>

代码参考:https://jets3t.s3.amazonaws.com/toolkit/code-samples.html

最新更新