HTTP 请求头的 Referrer-Policy 到底是什么?

1,460 阅读5分钟

当我们打开 Chrome 的网络面板,查阅它的任意一个请求,可以看到,请求中有一个 General 选项。

除了第四个,前三个我们都很熟悉。今天我们就来介绍一下第四个到底是什么。

image.png

Referrer Policys 是 HTTP 的一个请求头,通常结合着 Referer 来使用。直接讲这个属性可能会有点懵,我们一点点的逐层深入,最后你会发现,我们可以通过这一个属性把很多东西串起来。

首先,我先带大家了解一下 Referer

如果你去查这个英文单词对应的意思,多半是查不到的,原因很好玩,是因为最初在文档里的时候写错了,后面就延续了下来,这是一个很乌龙的事件。

它真正对应的英文单词是 referrer 。意思是引用、介绍人。在 HTTP 协议中,它的作用是表示我们当前的请求来自于哪里。

另外,值得注意的是,我们的 Referrer Policys 里的 referrer 是拼写正确的,同样的,我们在 JavaScript 的环境中获取这个值的时候拼写也是正确的:

document.referrer
// "https://developer.mozilla.org" 
// 这只是个一个示例,真实的结果因页面而定。

在一次 HTTP 请求中,我们可以选择携带 Referer ,也可以选择不携带。Referer 是一串网址,代表了当前的请求是从哪里发起的。

假如我们当前在 https://ven.example 这个网页。

如果这个主页上面需要加载一个图片 a.png,那它的值就是 https://ven.example。如果这个网站上的 style.css 文件某个 CSS 样式的背景是一个图片,那当请求这张图片的时候, Referer 值的格式可能就是 https://ven.example/style.css

你想现在就看看吗?点击 F12 ,并打开 NetWork,随意的找几个请求看一下这个属性到底是什么。

在继续下面的内容之前,我们先来介绍一下 URL 中几个 常用的概念。

假设我们有这样一个 URL: https://www.example.com:443/course/user/?id=5

在上述 URL 中,https://www.example.com 是源(origin),course/user 是路径(path),?id=5 是查询参数(querystring)。

而一个源又可以拆分为协议(protocol)、主机名(hostname)、端口(port)。

三者全部相同就是同源(same-origin),其他的就是跨源(cross-origin)。

image.png

Referer 的值可以说是 URL 的子集,它的值可以包含 URL 上的源(origin)、路径(path),查询参数(querystring)。而它可以包含上述三者中的那一些,就要根据 Referrer Policys 的值来确定了。

那为什么要有一个请求头来专门控制 Referer 呢?是因为稍有不慎,就可能引发潜在的安全问题。

假设我们停留在这样一个网页:

https://www.example.com/password_reset?username=wayne&token=12345

这时候,如果我们加载了一个图片,就会把这些信息携带在请求图片的 HTTP 请求的 Referer 里了。同样的,如果我们当前网站有一些外链,当我们点击这些外链的时候,也会把敏感信息带过去。

当然了,肯定不会有人这么不注意,在这里,只是为了表示这样的一个可能性。

现实生活中,泄露邮箱、用户名还是比较容易发生的:

https://www.example.com/my-account/mysteryven
https://www.example.com/email-verify?email=mysterven@example.com

为此,就有了 Referrer Policys 这个属性来限制 Referer 的值可以包含哪些东西。

我们先来看它的一个属性 strict-origin

它的意思是当请求不出现协议降级的时候(HTTPS -> HTTP属于降级)。我们请求头的 Referer 可以发送,但只会携带网址中的 origin 部分。如果出现了协议降级,就不发送 Referer 这个请求头了。值得大家注意的是,HTTP -> HTTP 或 HTTPS -> HTTPS 都不属于降级。


协议降级是什么?

举一个例子,我们当前网址是 HTTPS 协议的(https//example.com),但我们请求了一个HTTP 协议的图片(http://xxx.com/a.png),这时候就出现协议降级了。


现在,Chrome 浏览器默认的值是 strict-origin-when-cross-origin

它的意思是:在同源的时候,Referer 信息中的 origin、path、querystring 信息都可以发送。但是在跨域的时候,要遵循和 strict-origin 一样的规则,不降级的时候,只发送 origin 部分,降级了就什么也不发送了。

篇幅原因,我就省略其他属性的解释了,如果您感兴趣,请移步 MDN

最后就是一些设置 Referer 的手段了:

第一种就是在请求头里面加;

第二种可以在我们的 HTML 文件里面指定一个 meta 标签:

<meta name="referrer" content="strict-origin-when-cross-origin" />

如果我们使用了上面两种方法设置 Referer,它会优选选择我们设定的值。没有设定才会去使用浏览器的默认值。

虽然浏览器有默认的值,但是我们不能保证所有浏览器的默认值都是安全的,并且有的浏览器还能手动改这个的值。所以,为了保护用户信息,保险期间,我们可以自己在所有的请求里加上一个我们认为保险的选项(一般来说 strict-origin-when-cross-origin 就够了)。

写这篇博客的起因是我在搭 Mock 服务的时候遇到了一个和 Referer 相关的报错,但是却对解决那个报错没有任何头绪。后来发现是因为自己开代理了,真的被自己蠢哭。不过这件事让我学到了这个请求头是什么意思,也算是因祸得福吧。

好了,今天我们主要是讲解了 HTTP 里的两个请求头的含义,希望能帮到你,谢谢阅读!