OBS 对象突然 403:按桶策略、对象权限与防盗链三层定位的 6 步
周一上午,官网首页的图片突然全部打不开,浏览器里是一排裂开的小图标,接口返回的也不是图片,而是 403。对象本身没有删,桶也没有删,上一周还好好的。最后查下来,问题出在三个地方的叠加:桶策略只放行了旧域名下的路径、个别对象的 ACL 还是私有、晚上刚上线的防盗链白名单漏了新站点域名。单看任何一个都不觉得有问题,合在一起就是全站图片 403。本文把当时用的 6 步定位方法记下来,照着走基本能把 OBS 的 403 缩小到一个具体原因。
一、问题现象:先确认是 403,而不是 404 或 502
403 和 404 在页面上看起来差不多,都是打不开,但原因完全不同。404 是对象不存在或路径错了,403 是对象存在、但你没有读的权限。先分清这一步,后面才不会白改策略。
最直接的办法是用 curl 复现一次,顺便拿到状态码和响应头:
curl -s -o /dev/null -w "%{http_code}\n" https://my-bucket.obs.cn-north-4.myhuaweicloud.com/assets/logo.png
curl -I https://my-bucket.obs.cn-north-4.myhuaweicloud.com/assets/logo.png
如果返回 403,说明请求已经到了 OBS,鉴权或策略把它拦住了;返回 404,就先去核对对象键名是不是写错了、是不是大小写错了;返回 502 或超时,问题一般在 CDN 或网络层,不在桶策略上。当时我们拿到的是稳定的 403,而且换一台机器、换一个浏览器都一样,基本可以排除本地缓存和单个用户的问题。还有一个细节值得记下来:同一个桶里有的图片能打开、有的打不开,这种“部分 403”往往指向对象级 ACL 或防盗链,而不是整个桶的策略。
二、开始之前:先准备好这三样东西
动手改配置之前,先准备三样东西,避免边查边找权限。首先是 OBS 控制台的桶管理权限,至少能看到桶策略、对象 ACL 和防盗链配置;其次是出问题的完整对象地址,包括桶名、对象键、访问方式,是直接访问 OBS 域名,还是走了 CDN 域名;最后是最近变更的清单,例如昨天是否改过桶策略、是否有人单独改过某个对象、是否上线了新的前端域名或小程序域名。这三样东西在当时的排查里起到了关键作用:变更清单里有一条“昨晚给桶加了防盗链”,而出问题的图片恰好是从一个新域名引用的。
另外注意一个原则:在确认原因之前,不要直接把桶改成公开读来“先恢复业务”。公开读确实能让图片马上打开,但会把原本不该公开的对象也暴露出去。正确的顺序是先定位,再针对性放开最小范围,改完再验证、再复核。
三、分步操作:6 步定位 OBS 403
第 1 步:确认对象确实存在
先用 obsutil 看一眼对象是否还在桶里。配置一次后,就可以用命令行快速核对:
obsutil config -i=AK -k=SK -e=obs.cn-north-4.myhuaweicloud.com
obsutil ls obs://my-bucket/assets/
obsutil stat obs://my-bucket/assets/logo.png
obsutil ls 能列出指定前缀下的对象,obsutil stat 能看到对象的大小和存储类型。如果这里就找不到对象,那就是路径或键名的问题,跟权限无关,先去核对上传代码里的对象键。当时我们这一步是过的,对象存在,大小正常,所以继续往下查权限。注意不要把真实的 AK、SK 写进文章或提交到代码里,上面命令里的 AK、SK 只是占位符。
第 2 步:看桶策略有没有放行匿名读
在 OBS 控制台打开桶,依次看“权限控制 - 桶策略”。如果业务上需要匿名访问图片,策略里应当有一条允许所有人读取对象的声明,例如效果为 Allow、对象为该桶下需要公开的路径、动作为 GetObject。如果策略里只有登录用户可读,或者 Resource 只写了旧目录 old-assets/*,而新图片放在 assets/*,就会出现旧图能看、新图 403 的情况。
修改之前,先把现有桶策略完整复制保存一份。改完只放行确实需要公开的路径前缀,不要写成整个桶 /*。这一步改完后,重新用 curl 访问一次,看状态码是否变成 200。当时我们只放了 assets/*,仍有两张图片是 403,说明还有对象级的因素。
第 3 步:逐个核对打不开的对象的 ACL
桶策略放行了,不代表每个对象都放行。对象上传时如果没有继承桶的公开设置,单个对象的 ACL 仍可能是私有,桶策略和对象 ACL 都要满足才行。
在控制台进入桶的对象列表,找到打不开的图片,打开它的详情,看它的 ACL 或权限是不是“私有”。如果只有个别文件是私有的,单独把这几个对象的权限改为公共读,再重新访问一次。当时有两张图就是这样:它们是同事用另一套脚本单独上传的,上传参数里没有带公共读,控制台上逐个改回公共读后立刻恢复。以后上传公共图片,最好在上传代码里统一指定权限,或配置桶的默认权限,避免靠人工逐个补。
第 4 步:检查防盗链的 Referer 白名单
如果只有从网站页面打开图片才 403、直接在浏览器地址栏打开却正常,或者只有某个新域名引用的图片 403,基本可以锁定防盗链。
OBS 控制台的防盗链配置在桶的“防盗链”设置里,白名单里必须同时包含所有引用图片的域名,包括 www 主站、新上线的活动域名,以及小程序里使用的域名;如果配置里还勾选了“不允许空 Referer”,用某些客户端或直接下载工具访问时也会被拦截。可以用 curl 带上 Referer 复现:
curl -s -o /dev/null -w "%{http_code}\n" -e "https://www.example.com/" https://my-bucket.obs.cn-north-4.myhuaweicloud.com/assets/logo.png
curl -s -o /dev/null -w "%{http_code}\n" -e "https://new.example.com/" https://my-bucket.obs.cn-north-4.myhuaweicloud.com/assets/logo.png
两个命令只差 Referer,状态码一个 200、一个 403,就是防盗链白名单漏域名。当时漏的正好是新活动页的域名,补进白名单后恢复。不要把 * 写进白名单来图省事,那样防盗链就形同虚设了。
第 5 步:确认是不是临时链接过期了
如果图片地址是一串带签名的临时 URL,例如地址里带 X-Amz-Expires,403 也有可能是链接过期了,而不是权限配错了。临时 URL 过期后,OBS 会拒绝访问,表现同样是 403;重新生成一个未过期的临时链接再访问即可判断。如果重新生成的链接能打开,说明权限本身没有问题,是有效期设置得太短。
同时核对一下请求的域名:通过 CDN 访问时,CDN 侧也可能有自己的防盗链或鉴权,域名填错、或 CDN 上配置的回源 Host 与桶域名不一致,也会返回 403。出现这种情况,先绕过 CDN 直接访问 OBS 域名,确认 OBS 侧是否正常,再去处理 CDN 侧的配置。
第 6 步:看是谁最后改了配置
如果以上五步都没找到原因,就去看桶的配置变更记录和操作日志,确认 403 开始出现的时间点前后,谁改过桶策略、对象 ACL、防盗链或 IAM 权限。很多时候 403 不是配置从一开始就错,而是某次变更改错了范围,例如策略里的 Resource 少写了一个前缀、把效果写成了 Deny、或误删了一条放行规则。找到变更点之后,按第 2 步到第 4 步的方法逐项复核,而不是凭猜测再叠加一条新策略。
四、验证:改完要做这三件事
改完配置后,不要只在自己的电脑上刷新确认。这三件验证都通过了,再算修好:第一,用 curl 不带 Referer 和带两个不同 Referer 各请求一次,状态码应当都是 200;第二,分别从网站页面、直接打开图片地址、手机浏览器三个入口访问,应当都能正常显示;第三,让一位没有登录华为云账号的同事、或用浏览器的无痕模式访问一次,确认普通访客也能看到图。
我们当时还补了一件事:把本次改动的桶策略内容存了一份截图和文字记录,并把对象梳理成一张表,标清楚哪些目录是需要公开的、哪些目录必须保持私有。后续再出问题,可以直接对照这张表,而不用重新猜。
五、常见坑:五句话
一是“桶公开了就等于对象都公开了”,不对,对象 ACL 仍可能单独是私有。二是只在自己的浏览器上看到图片就以为修好了,自己的账号有管理权限,访客没有,两种身份看到的状态不一样。三是移动端图片裂开、PC 端却正常,往往是因为防盗链处理了空 Referer 或 APP 的域名没有进白名单。四是签名 URL 在代码里生成了很久才被打开使用,超过有效期后访问就变成 403,跟权限改动没有关系。五是修改没有生效被误认为“改了没用”,有可能是浏览器缓存或 CDN 缓存了旧的 403 响应,验证时要换一个文件名或用 curl 加上随机参数,例如 ?v=20261111,绕过缓存再测一次。
六、小结清单
- 复现:用
curl -I确认是 403 还是 404,记录第一个 403 出现的时间。 - 定位顺序:对象是否存在、桶策略、对象 ACL、防盗链、临时链接有效期、CDN 配置。
- 最小放行:只放行需要公开的路径前缀,白名单只加真实在用的域名。
- 统一上传:公共图片的上传参数要统一,禁止个别对象私自改成私有。
- 验证: curl、页面入口、无痕访客三个入口全部通过;改动内容留档;缓存干扰时用随机参数复测。
- 点赞
- 收藏
- 关注作者
评论(0)