图床加载失败?我们来看看发生了什么

最近在学习 fluuter,所以开发了一款应用,起名为:VVEX,数据都是通过模拟请求,解析 html 结构拿到的。

今天在手机上浏览主题时,发现在详情页会出现加载时白屏的情况,如下图。很明显可以判断是图片加载异常导致的问题。打开编辑器 🔨 ,复现一下问题,很明显我们图片资源出了点有问题

COPY
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
flutter: https://tutu.to/ttt_tvI99C.png
flutter: Exception: Invalid image data
flutter: Exception: Invalid image data
... ...
... inherit: false
... color: Color(0xff191c1b)
... family: NotoSansSC
... size: 14.0
... weight: 400
... letterSpacing: 0.3
... baseline: alphabetic
... height: 1.4x
... leadingDistribution: even
... decoration: Color(0xff191c1b) TextDecoration.none
... "load image failed, click to reload"
====================================================================================================

尝试在浏览器中打开,发现重定向到了 https://tutu.to/show/ttt_tvI99C-png,这就值得怀疑了,是不是在 app 中使用 http get 获取图片资源时,发生了重定向直接返回了 html 结构,并非有效的 bytes 数据,导致图片加载失败呢?


我们先尝试在postman中模拟请求,图片没有正常显示,返回了html结构

同样的,我们在 app 中直接使用 http 请求图片,跟 postman 返回了同样的 html 结构

COPY
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[log] <!DOCTYPE html>
<html lang="zh-CN" class="relative min-full">
<head>
<meta name="referrer" content="strict-origin-when-cross-origin" />
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<meta
name="csrf-token"
content="Qc2IhKwxEALVm7hdNXnLl8uaSBkpStYXnTlSvkOI"
/>
<title>loading</title>
<meta http-equiv="refresh" content="0.1;url=show/ttt_tvI99C-png" />

<script
defer
src="https://s.urstudio.cn/pixel/YIavbDTc6LktjXg2"
referrerpolicy="origin"
></script>
</head>
</html>

于是我在浏览器中访问原主题,发现图片可以正常显示,通过查看 Dom,发现 图片链接 也相同,另外在 image 标签上有额外两个属性:

COPY
1
2
referrerpolicy = "no-referrer";
rel = "noreferrer";

那么,跟这两个属性有关吗?

referrerpolicy

这个属性定义了 元素在获取资源时的引用方式。
属性有:

  • no-referrer:表示 HTTP 头部信息将不会发送 referrer
  • origin: referrer 只包含策略、主机名、端口等页面源的信息
  • unsafe-url: 这意味着引用者将包括源站和路径(但不包括片段、密码或用户名)。这种情况是不安全的,因为它可能会泄漏路径信息,这些信息已被使用 TLS 隐藏到第三方。
rel

另外 Referer单独讲

Referer 请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 请求头识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。

mark 此处,我们先继续往下看。

查看网络请求,发现图片资源的请求响应中并没有返回类似于 redirect 重定向的内容

复制 cURL 到 postman 模拟请求,图片可以正常返回,找到请求头中关键字段

COPY
1
'sec-fetch-dest' : image

关于Sec-Fetch-Dest在MDN上的说明

Sec-Fetch-Dest Fetch 元数据请求标头指示请求的目标,即数据的来源以及如何使用这些获取到的数据。
这允许服务器根据请求是否采用了适当的使用方式来确定是否为请求提供服务。例如,具有 audio 目标的请求应请求音频数据,而不是其他类型的资源(例如,包含敏感用户信息的文档)。

在此处我们使用指定 sec-fetch-dest 的类型为image,成功解决。


那么 Sec-Fetch-Dest 又是什么东东呢?
简单来说,就是网络请求的元数据描述,服务端根据这些补充数据进行细粒度的控制响应,换句话说,服务端可以精确判断请求的合法性,杜绝非法请求和攻击,提高web服务的安全性。

作者: 果汁
文章链接: https://guozhigq.github.io/post/6bb61c1a.html
版权声明: All posts on this blog are licensed under the CC BY-NC-SA 4.0 license unless otherwise stated. Please cite 果汁来一杯 !