我有app生成预签名网址(使用java sdk generatePresignedUrl方法)。 一切都在一个环境(@ EU_central_1服务器)上运行,但在其他环境(客户端的EU_West_1)上发布的相同应用程序会生成无法正常工作的链接,当我尝试在创建后立即下载对象时来自S3的信息网址:
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired</Message>
<X-Amz-Expires>600</X-Amz-Expires>
<Expires>2016-05-26T09:32:44Z</Expires>
<ServerTime>2016-05-26T09:33:03Z</ServerTime>
正如您所看到的,x-amz-expires设置为600秒,但是expires标签表示对象已立即过期。
这是一个问题吗? 计算错误的到期时间的 GeneratePresignedUrlRequest.setExpiration ?
我的代码设置过期时间:
Date expiration = new Date();
expiration.setTime(expiration.getTime() + 1000 * 600);
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key);
generatePresignedUrlRequest.setMethod(HttpMethod.GET);
generatePresignedUrlRequest.setExpiration(expiration);
URL url = s3client.generatePresignedUrl(generatePresignedUrlRequest);
看起来两台服务器同时返回。这是来自同一区域的连接到两个不同S3服务器的两个不同EC2服务器的响应。一个过期设置为4,第二个设置为4000(可以在创建链接后立即下载资源)。
服务器响应正常:
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired</Message>
<X-Amz-Expires>4</X-Amz-Expires>
<Expires>2016-05-31T09:54:04Z</Expires>
<ServerTime>2016-05-31T11:00:17Z</ServerTime>
来自具有预先签名的URL问题的服务器的响应:
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired</Message>
<X-Amz-Expires>4000</X-Amz-Expires>
<Expires>2016-05-31T10:49:54Z</Expires>
<ServerTime>2016-05-31T11:00:07Z</ServerTime>
同时创建两个链接(页面刷新时间差为几秒)
答案 0 :(得分:4)
签名V4(与V2不同)不依赖于签名生成代码来进行时间数学计算以确定到期时间。
生成V4签名(正如您所做)要求您知道现在的时间,并将该值包含为X-Amz-Date
。 AWS然后在他们身边做数学计算。 &#34;嘿,这个家伙说他11分钟前签了名,而且只有10分钟好了......被拒绝了!&#34;
检查生成签名的机器上的时钟。
答案 1 :(得分:0)
请参考以下文章以同步您的时间(在ec2和s3之间) https://aws.amazon.com/blogs/aws/keeping-time-with-amazon-time-sync-service/
我们需要使用名为chrony的服务。 其在ntp上的通用实现,并且更准确,更适应leap秒。
使用以下信息进行故障排除:
您可以使用date
命令来了解当前linux计算机中的时间。
X-Amz-Date
会告诉您何时在运行代码的ec2或计算机中签名了URL。
在答复中,
<Expires>2016-05-31T10:49:54Z</Expires>
<ServerTime>2016-05-31T11:00:07Z</ServerTime>
Expires根据X-Amz-Expires告诉您签名何时过期,ServerTime告诉您接收请求的时间在s3服务器上的时间。