【问题标题】:Why PHP redirect doesn't work when you pass the address of the page via GET?为什么通过 GET 传递页面地址时 PHP 重定向不起作用?
【发布时间】:2011-12-01 11:58:04
【问题描述】:

这是我在redirect.php 中的代码:(我知道这是不切实际的)

<?php
header("Location: " . $_GET['to']);
?>

这就是问题所在。此页面可以正常工作并正确重定向:

redirect.php?to=http://www.google.com

但是这个没有:

redirect.php?to=http://www.google.com/

问题不在于最后的斜线,这个也不起作用:

redirect.php?to=http://www.google.com/intl/en/about/corporate/index.html

urlencoded GET 请求也没有:

redirect.php?to=http%3A%2F%2Fwww.google.com%2F

但以下错误的确实有效:(注意 http:/ 中的一个斜杠)

redirect.php?to=http:/www.google.com/
redirect.php?to=http:/www.google.com/intl/en/about/corporate/index.html

这会导致我自己的服务器上出现 404 错误(“在我们的服务器上找不到请求的网址 www.google.com...”):

redirect.php?to=www.google.com/

在 Firefox 上,错误显示“与服务器的连接已重置”,Chrome 还显示“错误 101 (net::ERR_CONNECTION_RESET):连接已重置”页面。因此,我看不到服务器发送的标头。实际上它似乎没有发送任何!

有趣的是,当我在本地主机上使用 WampServer 测试所有上述请求时,它们都可以正常工作,但是当我上传它们时,它就不起作用了!标头之前没有输出或 BOM,没有使用代理,所有工作都在端口 80 上完成。可能是我的服务器配置(哪个配置?)问题的根源?

我想不出还有什么可以尝试和试验的。

我已经阅读了一些发送 POST 数据后重定向的问题,但我认为这与这个问题无关。

编辑:

尝试在 Location 标头之前发送 301 / 303 状态标头...没有运气。
打电话给朋友,让他用不同的 PC 和不同的 ISP 进行测试......没有运气。
用 ASCII 编码(而不是 utf8)写了另一个脚本……不走运。

请指出我可以对这个问题进行的其他测试和诊断。

【问题讨论】:

  • 如果您尝试redirect.php?to=www.google.com/ 并将您的标头设置为header("Location: http://" . $_GET['to']); 是否有效?
  • 您提供传递给redirect.php的参数,但最好提供它生成的标头。使用开发工具查看那些。
  • @positiv:这确实有效,但是有很多对 redirect.php 的引用,并且我的数据库中已经有一个相当大的可重定向链接数据库,我不想更改。
  • @Jon:你能提供更多信息吗?
  • @Col.Shrapnel:实际上没有。我错误地认为他试图传入RFC 1945 中定义的unsafe 组中的字符,这确实是一个问题。

标签: php redirect header get http-status-code-302


【解决方案1】:

这个没有:redirect.php?to=http://www.google.com/

否定。

urlencoded GET 请求也没有:redirect.php?to=http%3A%2F%2Fwww.google.com%2F

否定。

两者都有效。
您必须调试代码以找出问题所在。

  • 不要进行重定向和猜测结果,将收到的值打印到屏幕上并检查它
  • 您必须观看发送到浏览器的实际 HTTP 标头,而不是观看虚假的浏览器错误。

我想是 redirect.php 中的一些代码破坏了您的数据。类似愚蠢的“一次让所有数据安全”的例行公事。

【讨论】:

  • 正如我所解释的,由于 Chrome 和 Firefox 显示了它们的 Connection Reset 错误页面,DevTools 和 FireBug 都没有显示任何标题。请告诉我一些能够显示无法加载页面标题的工具?
  • @Col.Sharpnel:啊,就像我告诉你的那样,它在我使用 WAMP 的本地计算机上完美运行,当我真正将它上传到服务器时出现问题。是否有某种服务器配置可以控制此类事情的行为?
  • 如果您不重定向而仅将值打印出来,它会重置吗?
  • 在 chrome devtools 中,在访问 redirect.php 脚本之前打开网络选项卡。它可以向您显示发送和接收的实际标头。
  • @Col.Shrapnel: No. &lt;?php $r = "Location: " . $_GET['to']; echo $r; header($r); ?&gt; 打印出正确的输出:Location: http://www.google.com/ Warning: headers already sent...
【解决方案2】:

为什么不将其传递为urlencode(base64_encode($url)),然后重定向为base64_decode(urldecode($url))

它不能解决问题,但我很想知道这是否有效(它可能有助于识别潜在问题)。

【讨论】:

  • Base 64 编码确实有效。执行header("Location: http://" . $_GET['to'] . '/'); 也可以,但我对这种方式不感兴趣。
  • 我不会在最终实现中使用 base64。 @ErgoSummary:有人对这个问题中的每个帖子都投了反对票:S
【解决方案3】:

你不能实现这样的东西吗...

转到网址http://website.com/redirect.php?to=google.com

然后将您想要的位添加到 PHP 代码中的 URL,如下所示:

<?php
header("Location: http://" . $_GET['to']  . '/');
?>

您可以尝试对 URL 进行编码,然后在脚本中对其进行解码以防止异常

echo '<a href="redirect.php?to=' , urlencode("http://www.google.com/") , '">Click Here</a>';

然后解码它以进行重定向

<?php
header("Location: " . urldecode($_GET['to']) );
?>

【讨论】:

  • 我的一些链接可能是 ftp、smtp 等。而且我的网站充满了指向redirect.php 的链接,我不想更改每个案例。我正在寻找更通用的方法。不,urlencode 没有帮助(正如您在示例中已经看到的那样。)顺便说一句,您不知道 urldecode 不应该用于 $_GET 项目吗?
  • 两种解决方案都没有意义,而原始的 OP 的方法没问题。极具欺骗性的答案。
  • 我同意,欺骗性的回答,感谢 Luke Coulton;但已经尝试过了,没有运气。
  • 有点晚了,但是“urldecode 不应该用于 $_GET 项目”宁愿是“urldecode 不需要 用于 $_GET 项目”。然而,在极少数情况下它实际上会破坏 GET 数据。就像用户想要按字面意思发送 % 编码的字符或字符串的情况一样。
  • @Hossein 无用 - 可能。或者只是不是你要找的东西?这就是你要说的那句话!在这里“欺骗”的含义似乎有些混乱。有些答案不正确,但可能会激发其他想法的形成,从而有助于解决问题。
【解决方案4】:

您是否尝试在 php 标签之外寻找任何打印的字符?这会默默地破坏你的重定向。

尝试打开 php 标签。这将解决 php 结束标记后的空白问题。像这样的

<?php
header("Location: " . $_GET['to']);
// no closing tag and no content after

除此之外,这段代码是否包含在另一段代码中,该段代码可能在标头调用之前在 html 上打印了一些内容?

【讨论】:

  • 我很小心空格、换行符、BOM 字符等等。该文件既不包含也不包含。
【解决方案5】:

您不应该使用原始输入来发送标头,因为它会使您的应用程序容易受到response splitting attacks 的攻击。

你可以在SecuriTeam website找到一些很好的例子。

【讨论】:

  • 这只是一个小例子。在实际实现中,首先检查地址以确保它存在于有效链接的硬编码数组中。感谢您提供有用的链接。
猜你喜欢
  • 2014-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-19
  • 2015-10-09
  • 1970-01-01
  • 2018-08-15
相关资源
最近更新 更多