302重定向会保留referer字符串吗?

97
我需要将用户从一个页面重定向到另一个页面,但我需要保留原始的 referer 字符串。例如,如果他们最初在 http://www.othersite.com/pageA.jsp 上点击一个链接,然后跳转到 http://www.example.com/pageB.jsp,该页面执行 302 重定向到 http://www.example.com/pageC.jsp,我需要 referer 字符串包含 http://www.othersite.com/pageA.jsp
这是 302 重定向的正常行为吗?或者我的原始 referer 会被丢弃,以优先使用 http://www.example.com/pageB.jsp?那样不是很理想。
我不知道是否有任何区别,但我正在 JSP 中工作,并使用 response.sendRedirect() 执行 302 重定向。
我应该提到我已经进行了一次实验,它似乎保留了原始 referer 字符串 (http://www.othersite.com/pageA.jsp),但我只是想确保这是正常的默认行为,而不是我端口上的奇怪问题。
虽然我目前使用的是 302 重定向,但我可能可以改用 301 重定向。您知道 301 重定向的行为是否更可靠吗?

4
我能帮你做相反的事情。进行服务器端重定向,更改重定向时的来源(即删除原始来源)。有人可以做到吗? - cprcrack
5个回答

127

我不了解 302,但我今天在一些浏览器上测试了 301,以下是结果:

场景:用户在 domainX 上点击指向 domainA 的链接。domainA 进行 301 重定向到 domainB。

  • IE8 落地在 domainB 时的 referer 是:domainX(即使使用 InPrivate 浏览并且用户在新选项卡中打开链接)
  • Safari4 落地在 domainB 时的 referer 是:domainX(即使用户在新选项卡中打开链接)
  • FF3.6.10 落地在 domainB 时的 referer 是:domainX(即使用户在新选项卡中打开链接)
  • Chrome5 落地在 domainB 时的 referer 是:domainX(除非用户在新选项卡中打开链接)
  • Chrome26 落地在 domainB 时的 referer 是:domainX(即使用户在新选项卡中打开链接)

27
注意:这个测试是一段时间之前进行的,如今 Chrome 26 即使在新标签页中打开也会以相同的方式运行。 - BenMorel
尚未在所有浏览器上进行测试,但302状态码的行为似乎是相同的。 - Amir Ali Akbari
2
注意:如果重定向页面(domainA)发出_Referrer-Policy: no-referrer_头,则Chrome(和Opera)将不会在请求目标页面(domainB)时设置_Referer_头。Firefox和Edge仍然会发送它。 - David Balažic
1
Referer在Chrome和302重定向中不再发送。我找到并正在测试另一个解决方案,请参见我的回答https://dev59.com/WXI95IYBdhLWcg3wyBCc#71839517。 - Marco Marsala

36

简短回答是在相关的RFC 2616中没有指定Referer头或302状态码的行为 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36

您最好的选择是使用多个浏览器进行测试,并查看是否存在共识行为。

为了保险起见,将原始引用者编码到重定向URL中,以便您可以保证检索它。


23
有兴趣的人,我在主流浏览器上进行了一些测试:https://dev59.com/WXI95IYBdhLWcg3wyBCc#5441932 - Marco Demaio

13

很好的问题。在这种情况下,Referer的发送完全取决于浏览器(因为浏览器被告知向新资源发出另一个请求)。

RFC 2616 对此问题保持沉默:

所请求的资源暂时驻留在不同的URI下。由于重定向可能会随时更改,客户端应继续使用Request-URI进行将来的请求。只有在Cache-Control或Expires标头字段指示时,才可以缓存此响应。

我不会信任浏览器发送正确的Referer。我敢打赌至少有一个浏览器发送与其他浏览器不同的内容。

解决方法

如果可以的话,为您重定向到的URL添加一个?override_referer=<old_url>参数,并解析该值而不是HTTP_REFERER。

这样,您就可以确保始终获得正确的结果,并且安全性没有任何损失:无论哪种方式,Referer都可以被伪造。


7
通过允许URL中的Referrer被覆盖,实际上会降低安全性。在大多数现代浏览器中,通过JavaScript无法更改AJAX请求的Referrer;但是,显然可以更改URL。这意味着,在发生XSS攻击的情况下,Referrer比URL参数更可信。不要误解,Referrer仍然是明显的用户输入,不能完全信任。但是对于他人欺骗那些数据而言,伪造Referrer要困难得多,相比之下更容易更改URL。 - phylae

9
我有相反的问题:我希望referer是"pageB",但目前的浏览器都不会这样处理...
所以我尝试在pageB上使用HTML重定向(而不是301或302重定向):
<meta http-equiv="refresh" content="0; url=pageC.jsp" />

结果令人惊讶:

  • 使用Chrome时,Referer是页面B。
  • 使用FireFox和IE时,Referer为空!

希望这可以帮到您。


现在使用Chrome也是空的。应该采用一个有效的JavaScript重定向。 - Marco Marsala

1
来晚了,但今天HTTP重定向(无论是通过HTTP标头还是meta http-equiv)都不会在Referer标头中发送重定向页面。
所有情况下,Javascript重定向似乎都会在Referer标头中发送重定向页面。 <script>window.location.href="..."</script> 我有以下场景:
- 域A上的着陆页; - 域B上的Web应用程序。
如果已经登录到Web应用程序的用户访问着陆页A(例如从搜索引擎或按点击量计算的广告系列过来,这占我们大部分的流量),它应该自动重定向到Web应用程序B。 这是一个CORS方案,但我控制两个域。
我可以通过正确设置/读取跨域Cookie(使用HTTPS + Secure + SameSite Cookie属性时有效)来实现这一点,但当用户从Web应用程序注销,或仅清除了两个域之一的浏览器Cookie,或会话在服务器上过期时,它会有一些缺点。
所以我想出了另一个解决方案:在我的Web应用程序B中实现了一个端点“/redirectIfNotLogged”。当有人访问着陆页A时,会执行HTTP重定向到域B上面的该端点。该端点读取cookie并检查会话。如果用户已经登录,则重定向到Web应用程序的仪表板;否则,它将重定向回网站。为避免无限重定向,我必须知道我们是否来自Web应用程序操作的重定向。我们将重定向到原始URL,而不是重定向到域A上的其他页面或附加查询字符串。因此,我检查HTTP Referer标头。我发现通过Javascript进行的重定向会发送Referer标头,而HTTP重定向则不会。Web应用程序需要使用Javascript才能工作,因此这不是问题。
仍在尝试一些防病毒软件或防火墙(我们在所有地方都使用HTTPS,因此我不关心云或企业AV / FW或任何未安装在本地机器上的东西)是否会剥离Referer标头。在这种情况下,我只需选择显示着陆页A(或Web应用程序B),以避免无限重定向。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接