在制作本博客时,有一个文章页生成二维码的一个小需求,简单来说就是传入一个URL返回一个二维码图片。于是自然的就想起了浏览器在发出HTTP请求时通常会默认把来源URL添加到HTTP的请求头Referer字段的这么一个特性
GET /qrcode HTTP/1.1
Host: www.qttc.net
Referer: https://www.qttc.net/about.html
于是页面上显示二维码的代码这么写
index.html
<img src="https://static.qttc.net/qrcode" />
服务器端生成二维码的就直接取Referer字段,以下是代码片段
server.js
const requestHandler = (req, res) => {
qrcode.generate(req.header['Referer']).pipe(res);
};
server.addRoute('/qrcode', requestHandler);
但在部署之后,扫码发现所有的二维码识别出来的地址一律都是https://www.qttc.net/
,好奇怪。
GET /qrcode HTTP/1.1
Host: static.qttc.net
Referer: https://www.qttc.net/
仔细看了一下,发现img里的所有请求Referer字段不包含path, query search,到MDN Web Docs下找到了原因
referrerpolicy
属性下的origin-when-cross-origin
是这么解释的
origin-when-cross-origin: Navigating to other origins will limit the included referral data to the scheme, host, and port, while navigating from the same origin will include the full path and query string.
意思是img请求的图片地址域与页面域发生跨域时,Referer只会发送三个部分的内容
- scheme
- host
- port
因为我是在www.qttc.net
页面下发出的https://static.qttc.net/qrcode
请求,属于跨域了,所以请求头里一律都是https://www.qttc.net/
,解决这个问题可以在img标签加上这个属性referrerpolicy
,值写上unsafe-url
,如下
官方的解释
unsafe-url: The Referer header will always include the origin, path and query string, but not the fragment, password, or username. This is unsafe because it can leak information from TLS-protected resources to insecure origins.
总结来说,就是如果使用了这个特性会导致TLS
资源信息的泄露,比如你的query string有敏感数据的话。但在我这个Case里不存在这个问题,所以我在二维码的img标签上都加了这个属性
<img src="https://static.qttc.net/qrcode" referrerpolicy="unsafe-url" />
再次测试,Referer里已包含path, query string
GET /qrcode HTTP/1.1
Host: static.qttc.net
Referer: https://www.qttc.net/539-rust-webassembly-example.html
二维码已按来源地址生成,测试成功!