我想将用户个人资料图片存储在 S3 存储桶中,但将这些图片保密。为了做到这一点,每当需要图像时,我都会创建一个预签名的 url。但是,这每次都会创建一个唯一的 url,这意味着图像永远不会被浏览器缓存,我最终会在 GET 请求中付出更多。
这是我生成 url 的代码示例,我使用的是 Laravel:
$s3 = \Storage::disk('s3');
$client = $s3->getDriver()->getAdapter()->getClient();
$expiry = new \DateTime('2017-07-25');
$command = $client->getCommand('GetObject', [
'Bucket' => \Config::get('filesystems.disks.s3.bucket'),
'Key' => $key
]);
$request = $client->createPresignedRequest($command, $expiry);
return (string) $request->getUri();
我认为通过指定日期时间而不是时间单位,它会创建相同的 url,但它实际上将剩余的秒数添加到 url,这是一个示例:
xxxx.s3.eu-west-2.amazonaws.com/profile-pics/92323.png?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AXXXXXXXXXXX%2Feu-west-2%2Fs3%2Faws4_request&X-Amz-Date=20170720T112123Z&X-Amz-SignedHeaders=host&X-Amz-Expires=391117&X-Amz-Signature=XXXXXXXXX
是否可以生成可重复的预签名请求 url,以便用户浏览器可以缓存图像?
最佳答案
这是我在关注这篇文章后想出的 python 解决方案。 它使用 freezegun库来操纵时间以使签名在给定时间段内相同。
import time
import datetime
import boto3
from freezegun import freezetime
S3_CLIENT = boto3.client("s3")
SEVEN_DAYS_IN_SECONDS = 604800
MAX_EXPIRES_SECONDS = SEVEN_DAYS_IN_SECONDS
def get_presigned_get_url(bucket: str, key: str, expires_in_seconds: int = MAX_EXPIRES_SECONDS) -> str:
current_timestamp = int(time.time())
truncated_timestamp = current_timestamp - (current_timestamp % expires_in_seconds)
with freeze_time(datetime.datetime.fromtimestamp(truncated_timestamp)):
presigned_url = S3_CLIENT.generate_presigned_url(
ClientMethod="get_object",
Params={
"Bucket": bucket,
"Key": key,
"ResponseCacheControl": f"private, max-age={expires_in_seconds}, immutable",
},
ExpiresIn=expires_in_seconds,
HttpMethod="GET",
)
return presigned_url
关于php - AWS S3 预签名请求缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45213553/