解决腾讯云 COS 客户端报 Request has expired 的问题

您所在的位置:网站首页 云报客户端 解决腾讯云 COS 客户端报 Request has expired 的问题

解决腾讯云 COS 客户端报 Request has expired 的问题

2024-07-10 19:41| 来源: 网络整理| 查看: 265

背景

我有一段 python 代码,是用于与腾讯云对象存储服务 COS 进行交互,从而实现对象搜索、对象下载等功能。 本地调试没问题后,想利用 docker 实现容器化部署,却报错了,提示 “AccessDenied” 以及 “Request has expired"。明明各种配置参数都一样,为什么换个地方就运行不了了呢。

结论

这里先给出根本原因和解决方案:

根本原因:容器的系统时间与真实时间不一致(一般是远远落后于真实时间),导致 COS 客户端在发起请求的时候,签名过期,请求失败。解决方案:共有 3 类方案: 容器使用宿主机的本地时间设置:将宿主机的 /etc/localtime 文件挂载到容器的相同路径下,并以只读模式 (ro) 进行挂载即可。但我的情况比较特殊——使用的是 podman 而非 docker,容器内的时间实际上是与虚拟机同步的,修改虚拟机的时间设置比较麻烦,折腾了一小时没成功,最终放弃这种方案。容器使用 NTP(网络时间协议)客户端与 NTP 服务器同步时间:在容器内安装和配置 NTP 客户端,然后使用 NTP 服务器同步时间。但需要装一堆东西,很麻烦,我的容器是 alpine 系统(一个面向安全的轻型 Linux 发行版),很多包都需要重新安装,折腾了一小时没成功,最终放弃这种方案。传递 cos 签名超时参数:相比于前面两者比较治本的方法,这种方式有点头痛医头的感觉,并且是绕过了问题。因为如果你用 time.time 或其他方法读取时间,读到的还是错误的时间。但无所谓了,能解决问题就行,详见下文。😂如果你有好的方法,也欢迎在评论区回复,感谢~ 过程分析 定位问题

首先,通过翻阅官方文档,可以看到一段解释说明。 在这里插入图片描述

看上去是时间设置的问题,对比本地和容器内的时间,可以知道已经不是简单的时区问题了。因为时区一般是差 N 小时,而这已经是差了好几天了。

在这里插入图片描述

解决方案 1. 容器使用宿主机的本地时间设置

需要注意的是,该方案不适用于 podman。

在这里插入图片描述 在这里插入图片描述

2. 容器使用 NTP(网络时间协议)客户端与 NTP 服务器同步时间

如何安装 NTP 客户端并设置,跟你的系统有关,并没有统一的方案。同样操作起来很麻烦……

在这里插入图片描述 在这里插入图片描述

3. 传递 cos 签名超时参数

折腾了半天无法解决这个问题后,我决定不再想着如何根治问题,而是针对于这个案例来定向解决。

首先,根据代码报错的位置,可知是请求的时候报错,具体是在 cos_client.py 的 1391 行。这段代码主要做的就是把 URL、params、headers 以及跟用户认证有关的内容,传递给 send_request 方法,发起请求。

在这里插入图片描述 跟签名过期有关的内容,一般要么放在 header 里,要么放在 auth 里,依次查看内容后,很容易看到答案就在 CosS2Auth 里。但麻烦的是,我们并没有办法传递或修改这个 expire 参数值。

在这里插入图片描述 在这里插入图片描述

那么只能把这段代码复现一下,唯一区别就是指定了 CosS2Auth 里的 expire 值。

下面以 list_objects 举个例子:

修改前,直接使用 cos_client 对象的 list_objects 函数

cos_client.list_objects(Bucket=bucket, Prefix=prefix, Delimiter="/", Marker=marker)

修改后,把 list_objects 的源代码拷贝出来,放在自己重新定义的 list_objects 函数里,但是额外在初始化 CosS2Auth 实例时传递 expire 值。

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3