阿里云官网给的PHP、GO的OSS直传签名的时间算法是错的

更新: 2020-09-03

阿里云官方已经修正了Golang的示例  https://connect.console.aliyun.com/connect/detail/162632

PHP相关的我给一些项目提了 PR https://github.com/iiDestiny/flysystem-oss/pull/52/commits/07d7adf2d7dc4b3352a1258bee34db9e371fd4b7

今天是 2020-08-15

比正确时间晚8个小时

阿里云官网给的例子是 https://help.aliyun.com/document_detail/91771.html#concept-nhs-ldt-2fb 

对应下载链接 http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/92590/APP_zh/1539603337889/aliyun-oss-appserver-php-master.zip?file=aliyun-oss-appserver-php-master.zip

里面有个计算过期时间的函数

其输入参数是Unix时间戳。这是一个把Unix时间戳转换成iso8601格式的算法,但是稀奇的是,阿里云给的例子,是直接把ISO8601的格式结尾的时区裁剪掉,改成0时区(Z),而我们知道,如果你系统本身就是0时区,那么这个做法没什么问题,如果你系统是东8区呢?那么生成的时间字符串所代表的过期时间就比实际期望的时间晚8个小时。

比如现在是东八区2020-08-15 14:15:30我输入如下参数,期望这个签名在30秒后过期。

实际输出的是 2020-08-15T14:16:00Z, 这是一个ISO8601的格式,表示是0时区2020-08-15 14:16:00,换算成东八区就是 2020-08-15T22:16:00+8 比我期望的 2020-08-15T14:16:00+8 晚了整整八个小时。

这种偏差在正时区还好,不影响业务,顶多就是过期时间比预期的长很多,如果在负时区呢?

输出的是Z,直接报错了。

就算把系统默认时间改成正时区,不报错,但是输出依然是有误差的。

再来看看其他语言的SDK,这是阿里云官网的Golang文档 https://help.aliyun.com/document_detail/91818.html#title-io0-22w-4f3,代码包下载 http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/86983/APP_zh/1538029675267/aliyun-oss-appserver-go-master.zip?file=aliyun-oss-appserver-go-master.zip

我们来看看Golang这个示例怎么实现这个方法的:

很明显,他这边实现就是把unix时间戳直接格式化为ISO8601格式并且丢掉了时区信息统一设置为0时区

写个完整的程序跑了一下一样的结果。

那么这个时间差是否被OSS网关承认呢

到底这个时间戳有效期是我们设定的30秒还是8个多小时呢?我特意用"正确"的实现(当前时间转换为0时区时间)和错误的实现(直接丢掉时区信息强制设置为0时区)

我认为的正确实现,以Carbon为例

Carbon会把当前时区用GMT时区表示(不是简单的抹掉时区,而是加减到当地时间)

测试结果是,用正确时间算法,生成的policy就正好在60秒后过期。说明OSS的网关也是按照认为的正确算法来验证时间的,而用官网自带Demo实现的60秒过期算法,在几个小时后,这个policy还能够正常上传,直到8小时以后。看来自家网关实现的时候也是按照我认为的正确逻辑来实现的。

阿里这个低级错误不改犯。

正确的实现

刚才上面已经用Carbon给出了正确的时间实现,所以对应正确的Golang实现应该是这样的:

如果不用Carbon的实现 用PHP自带的实现是这样的

不知道阿里云什么时候会改过来

 

Author Info :
  • From:阿里云官网给的PHP、GO的OSS直传签名的时间算法是错的
  • URL:https://blog.ihipop.com/2020/08/5260.html
  • Please Reserve This Link,Thanks!
  • 《阿里云官网给的PHP、GO的OSS直传签名的时间算法是错的》上有1条评论

    1. 哈哈哈哈,博主很细心呐。时区问题是最常见的新手问题之一,妹想到= =阿里的程序员也会犯这样的错误~

    发表回复

    您的电子邮箱地址不会被公开。 必填项已用*标注