HTTP字段referer学习

64 阅读2分钟

前言

最近排查一个问题,页面上有几个三方(跨域)接口,HTTP请求头没有带referer信息,要求前端排查原因。

web页面是通过服务端接口返回的,服务端是nodeJS/Koa框架。

什么是referer?

Referer是HTTP请求头中的一个字段,用于指示当前请求的来源页面URL.当用户从一个页面点击链接访问另一个页面时,浏览器会自动在请求头添加这个字段。

image.png

referer有什么作用?

referer的本质作用是“告诉服务端,我从哪里来”。
主要用于统计、业务判断等。 但不安全、不可靠,受浏览器策略严格控制, 只能作为辅助信息。

从浏览器端排查

为什么第一判断是从浏览器排查呢?
因为三方请求是从当前页面发出的,也不会经过当前页面所在服务端。

1. 普通页面跳转/资源加载,浏览器默认会自动携带Referer

<a href="https://example.com">link</a>
<img src="https://example.com/a.png" />
<script src="https://example.com/a.js"></script>

2. 可以使用 Fetch API 提供的专用选项来设置

fetch('https://example.com/api', { // 只能设置为当前源或空字符串
    referrer: 'https://www.lenovo.com/', // 必须是同源URL // 指定引用策略 
    referrerPolicy: 'strict-origin-when-cross-origin' // 其他合法值: 'no-referrer', 'no-    referrer-when-downgrade', // 'origin', 'origin-when-cross-origin', 'same-origin', 'strict-origin' 
});
  • no-referer 永远不发送
  • origin 只发送域名
  • same-origin 仅同源
  • strict-origin-when-cross-origin
    • 当请求目标与当前页面同源,发送完整URL作为Referer(包含路径、查询参数等)
    • 当请求目标与当前页面不同源时:只发送origin,不包含路径和查询参数
  • unsafe-url 完全url

3. 使用HTML meta标签

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

了解了以上知识点,网页meta标签没有任何设置,其次接口请求也没有设置。
网页添加上如上配置之后,HTTP的request请求头中还是没有带referer。

排查服务端

服务端也没有显示设置,这就奇怪了!
于是尝试在服务端直接设置referrerPolicy:

// 安全头
app.use(
    // 修改 Referrer-Policy,允许在同等安全级别下发送 Referrer (如 https -> https)
    referrerPolicy: { policy: "no-referrer-when-downgrade" },
  }),
)

让我们了解一下 no-referrer-when-downgrade 与 strict-origin-when-cross-origin 的区别:

情况no-referrer-when-downgradestrict-origin-when-cross-origin
HTTPS → HTTPS (同源)完整 URL完整 URL
HTTPS → HTTPS (跨源)完整 URL仅源 (origin)
HTTPS → HTTP无 Referer无 Referer
HTTP → 任何完整 URL完整 URL (同源) / 仅源 (跨源)

一测试,居然HTTP Request都带上了referer!!!
这是为什么呢?

原因如下: 该页面从服务端接口返回的。页面HTTP的response中携带了了Referrer policy: no-referer。如图所示:

image.png

当服务器在 HTTP 响应中设置了 Referrer-Policy 头部时,它会覆盖浏览器的默认行为,成为该页面及其资源请求的权威策略

总结

  1. 学习了什么是referer字段和referer字段的作用
  2. HTTP 响应头中的 Referrer-Policy 拥有最高优先级