解决openlist对象储存403报错
前不久给自己的OSS图床开启了防盗链,限制只有自己的网站才能访问,结果一打开OpenList,发现里面的图片全都挂了。
明明已经把自己的子域名加进白名单了,为什么还是被拦截?折腾了一番后总算解决了,记录一下整个排查过程。
一、排查原因:请求没有携带Referer
打开OpenList网盘页面,进入开发者工具在Network中刷新页面,找到加载失败的图片请求。
查看响应信息,发现返回的是403 Forbidden,第一反应就是OSS防盗链拦截了请求。
但有点奇怪,我明明已经把自己的子域名加入了白名单,按理说不应该被拦截才对。
继续检查请求头,发现问题所在:请求里根本没有Referer字段。
而我的OSS防盗链设置恰好是不允许空Referer访问,所以请求直接被拒绝了。
接着检查OpenList页面,发现HTML的头部有这样一行配置:
<meta name="referrer" content="same-origin">问题就出在这里。
虽然网盘和图床都属于同一个主域zwfpro.com,但它们并不是同一个Origin(源)。same-origin策略只会在同源请求中发送Referer,跨子域请求则不会携带。
所以,即使OSS白名单配置正确,还是会因为请求没有Referer而返回403。
二、尝试方案一:在自定义头部添加meta标签(无效)
既然找到了原因,第一个想到的就是OpenList后台自带的「自定义头部」功能。
于是直接添加了新的Referer策略:
<meta name="referrer" content="strict-origin-when-cross-origin">保存后刷新页面,图片依旧加载失败。
重新检查页面,发现原来的same-origin和新添加的策略同时存在,并没有替换掉原来的标签。
看来这个方法行不通,继续折腾。
三、尝试方案二:通过自定义内容注入JavaScript(无效)
后台还有一个「自定义内容」功能,可以插入HTML和JavaScript。于是又尝试通过脚本修改原来的标签:
<script>(function () { var meta = document.querySelector('meta[name="referrer"]'); if (meta) { meta.setAttribute('content', 'strict-origin-when-cross-origin'); }})();</script>思路很简单:找到原来的meta标签,直接修改它的content属性。
但实际测试后,图片还是403。问题在于,这种方式无法保证脚本执行时图片请求还没有发出,单纯修改标签也不能保证首次请求就使用新的策略。
连续试了两种方法都没成功,只能换个思路。
四、最终方案:使用外置前端资源
难道只能修改OpenList前端源码,再重新编译整个二进制文件?
其实没必要这么麻烦,查看OpenList官方文档后,发现可以通过data/config.json中的dist_dir配置指定前端资源目录。也就是说,可以单独修改前端文件,让OpenList加载修改后的资源,不需要重新编译后端。
1. 确认OpenList版本
先进入OpenList安装目录,查看当前版本:
./openlist version我的版本是v4.2.6,因此后续下载的前端资源也选择对应版本,避免前后端版本不一致。
2. 下载对应版本的前端资源
前往OpenList-Frontend官方发布页面:
找到与当前OpenList版本对应的发布包。这里我选择的是标准版openlist-frontend-dist-v4.2.6.tar.gz,而不是Lite精简版,尽量避免前端功能差异。
3. 解压并修改前端文件
在OpenList安装目录下的data文件夹中创建dist目录,将下载的前端压缩包解压进去。
目录结构需要注意,确保index.html直接位于dist目录中,而不是多嵌套一层文件夹。例如:
/openlist安装目录/├── openlist└── data/ ├── config.json └── dist/ ├── index.html └── 其他前端资源接着编辑data/dist/index.html,找到原来的标签:
<meta name="referrer" content="same-origin" />将其修改为:
<meta name="referrer" content="strict-origin-when-cross-origin" />这样,HTTPS页面请求HTTPS图片时,浏览器就可以发送来源站点的Referer,而不会附带完整的页面路径和查询参数。
4. 修改OpenList配置
打开安装目录下的data/config.json,找到 dist_dir 配置项。
原来的配置是:
"dist_dir": ""修改为实际的前端资源目录:
"dist_dir": "/openlist安装目录/data/dist"这里填写的是服务器上的绝对路径,需要根据自己的实际安装目录修改。其他配置保持不变即可。
5. 重启OpenList
保存配置后,执行:
systemctl restart openlist重启完成后,浏览器按Ctrl + F5强制刷新页面。
6. 验证修改是否生效
重启后不要急着判断是否成功,先确认OpenList是否真的加载了修改后的前端文件。
第一步:检查页面源码
确认原来的:
<meta name="referrer" content="same-origin" />已经变成:
<meta name="referrer" content="strict-origin-when-cross-origin" />如果仍然是same-origin,说明修改后的前端资源可能没有生效。可以检查dist_dir路径是否正确,并清除浏览器缓存后重试。
第二步:检查图片请求
打开开发者工具,进入Network,重新加载页面,找到加载失败的图片请求,查看请求头。
确认请求中已经出现:
Referer: https://img.xxx.com/且图片请求的响应状态码应该由403 Forbidden变为200 OK
确认页面源码和请求头都正常后,基本就可以确定这次修改已经生效,至此,图片终于正常显示了。
如果Referer已经出现,但图片仍然返回403,就需要继续检查OSS防盗链白名单、黑名单及其他访问规则。
最后
这次问题其实不复杂,根源就是same-origin策略导致跨子域图片请求没有携带Referer。
前面两种方法没成功,主要是因为追加标签并不能替换原有策略,而注入脚本又存在执行时机的问题。最后通过dist_dir使用外置前端资源,只修改一个HTML标签就解决了,不用动后端二进制文件。
如果以后升级OpenList,需要留意前后端版本是否匹配,以及外置前端资源是否需要同步更新。
如果不再需要外置前端,也可以将dist_dir恢复为空字符串,让程序使用内置资源。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分内容可能已过时
岁语集