33

是的,以前有人问过这个问题,但是答案并不一致。为什么我必须在通过 PHP 中的 header('Location..') 重定向后调用'exit'?例如。每个答案(包括接受的答案)都表明是,除了最后一个答案是零票,上面写着“也许”。我开始认为正确的答案是“也许”。为了使它成为一个简单的“是”或“否”问题,doThis() 会在给定以下脚本的情况下执行吗?谢谢

header('Location: http://somewhereElse.com');
//die();
sleep(1000);
doThis();

编辑谢谢,所有。使用我的 PHP/Linux/Apache 配置,第二个 syslog() 执行,所以答案是“是的,将执行标头下游的所有脚本”。我会假设(并希望我是正确的)所有 PHP/Linux/Apache 配置都是一样的!

<?php
  header('Location: http://google.com');
  syslog(LOG_INFO,'first');  
  sleep(5);
  syslog(LOG_INFO,'Second');  
?>
4

10 回答 10

31

header('Location: http://google.com')是的,如果您没有明确终止脚本,则调用后脚本将继续处理!我只是在本地尝试过。我将 test.php 添加到 apache 中的一个站点,其中包含以下内容:

<?php

header('Location: http://google.com');
error_log("WE MADE IT HERE SOMEHOW");

?>

并检查了我的 /var/log/apache2/error_log 这个条目:

[Tue Feb 12 23:39:23 2013] [error] [client 127.0.0.1] WE MADE IT HERE SOMEHOW

可能令人惊讶,但是是的,如果您不停止执行,它会继续执行。

于 2013-02-13T05:41:25.567 回答
12

人们似乎对此感到非常困惑,以及执行脚本的原因。当您发送重定向标头时,浏览器会立即将用户重定向到新页面,但您的服务器将继续处理代码,即使最后没有人接收它,这并不意味着脚本已终止。除非您将 Apache 配置为在发现另一端没有脚本时停止脚本。

当 PHP 脚本正常运行时,NORMAL 状态处于活动状态。如果远程客户端断开连接,则 ABORTED 状态标志打开。远程客户端断开连接通常是由用户点击他的 STOP 按钮引起的。

您可以决定是否希望客户端断开连接导致脚本中止。有时,即使没有远程浏览器接收输出,始终让脚本运行完成也很方便。但是,默认行为是在远程客户端断开连接时中止您的脚本。可以通过 ignore_user_abortphp.ini 指令以及相应的 php_value ignore_user_abortApache httpd.conf 指令或 ignore_user_abort()函数来设置此行为。

无需进一步操作即可重定向用户的正确方法是:

header("Location: blah.php");
exit();
于 2015-05-25T03:50:21.673 回答
5

让我再解释一下。让我们举一个使用会话的例子。

$_SESSION["username"] = 'some username';
header("Location: another-file.php");
$_SESSION["username"] = 'replace username';

的结果$_SESSION["username"]将是replace username

您可以输出更多的标头,而不仅仅是Location带有标头的标头,其中大多数您不想停止代码执行。如果要停止代码执行,则需要exit显式调用。

header命令不会中断您的代码流。即使遇到这种情况,浏览器仍然会下载您的页面,即使它没有显示。考虑404 pages,其中(尽管有错误)仍然由浏览器处理(尽管它们在重定向时被渲染)。

于 2013-02-13T05:44:26.123 回答
3

运行代码:

//http://www.php.net/manual/en/function.header.php
header('Location: http://google.com');
flush();
sleep(3);

$a=fopen('test.txt', 'w');
fwrite($a,headers_sent());
fclose($a);

在客户端重定向我之前,服务器暂停并写入文件。这是因为,即使在flush()ing 缓冲区之后,重定向也不会被处理,直到脚本停止执行(即脚本终止)。该文件在每种情况下test.txt都有'1' ,这意味着标头已发送,只是在连接终止之前浏览器不处理。

  • 在任何情况下,都意味着在 win32 开发机器、linux 开发机器和 linux 生产环境上。
于 2013-02-13T05:51:34.337 回答
2

重定向完成后脚本仍将运行。尽管有时它可能有用,但使用header函数的人必须意识到它可能很危险。看看这段非常不安全的代码:

<?php
if($_GET['some_secret'] != '123') {
    setcookie("status", "not logged in");
    header("Location: /");
}
setcookie("status", "logged in");

echo("Some secret info!")
?>

无论您输入什么some_secret,您都将始终拥有一个 cookie,其值为logged in。这里唯一的区别是如果给出了错误的参数值,用户将被重定向。

解决方法:使用die()orexit()方法在重定向后立即结束脚本

这个小的更正将使我们的脚本按我们想要的方式工作。

<?php
if($_GET['some_secret'] != '123') {
    setcookie("status", "not logged in");
    header("Location: /");
    die();
}
setcookie("status", "logged in");

echo("Some secret info!")
?>

(我不会用else语句展示另一个简单的解决方案,因为这不是真正应该这样做的方式。)


您可能会认为,用户至少不会看到您在屏幕上打印的秘密信息。错误的!浏览器只是进行重定向,但我们是否遵循它取决于我们。

在这个例子中,我使用了一个没有漏洞的代码die

$ telnet 192.168.1.39 80
Trying 192.168.1.39...
Connected to 192.168.1.39.
Escape character is '^]'.
GET /test.php?some_secret=wrong
Some secret info!
Connection closed by foreign host.

如您所见,秘密信息泄露。

所以,请注意,这header可能非常不安全!
...并记住通常不要以明文形式存储密码等数据或登录 cookie 等信息

于 2019-05-21T16:00:42.073 回答
2

第一个示例显示在标头位置重定向之后执行了一些代码,但并非所有代码都必须执行。一旦浏览器开始响应重定向标头,它将终止当前页面上的连接,这将导致 PHP 终止执行其代码。这显示了如何不做事。

session_start();
$_SESSION["some_value"] = 'original value';
header("Location: /index.php/test2");

$start_time = microtime(true);

for($i = 0; $i <= 100000; $i ++)
{
    password_hash($i);  // slow it down
    $_SESSION["some_value"] = $i;   
    $_SESSION['time'] = microtime(true) - $start_time;
}

$_SESSION['some_value'] = 'finished!';

// Result:
// some_value = 174

在此示例中,我添加了 ignore_user_abort() 以显示如何执行所有代码:

ignore_user_abort(TRUE);
session_start();
$_SESSION["some_value"] = 'original value';
header("Location: /index.php/test2");

$start_time = microtime(true);

for($i = 0; $i <= 100000; $i ++)
{
    password_hash($i);  // slow it down
    $_SESSION["some_value"] = $i;   
    $_SESSION['time'] = microtime(true) - $start_time;
}

$_SESSION['some_value'] = 'finished!';

// Result:
// some_value = finished!

这就是您通常执行重定向的方式,方法是在重定向后立即终止脚本:

session_start();
$_SESSION["some_value"] = 'original value';
header("Location: /index.php/test2");
die();

$start_time = microtime(true);

for($i = 0; $i <= 100000; $i ++)
{
    password_hash($i);  // slow it down
    $_SESSION["some_value"] = $i;   
    $_SESSION['time'] = microtime(true) - $start_time;
}

$_SESSION['some_value'] = 'finished!';

// Result:
// some_value = original value

简而言之,要么使用 die(),exit(),要么使用 ignore_user_abort(TRUE);

于 2017-02-28T17:17:42.160 回答
1

是的,它将在短时间内执行。

一旦重定向标头发送到浏览器,浏览器将关闭当前连接并为重定向 URL 打开一个新连接。在关闭原始连接并且 Apache 关闭脚本之前,您的代码将继续像以前一样执行。

理论上,如果客户端/服务器之间有足够快的连接,并且管道中没有任何缓冲,则发出标头将导致脚本立即终止。实际上,可以在“现在”和“从不”之间的任何时间启动关闭。

阅读更多

于 2013-02-13T05:42:34.853 回答
0

是的,是的,header 和 php 脚本的任何其他部分一样,它将在脚本执行完成后发送,但是,诀窍是:如果我们要重定向到新的 URL:那么为什么要在 header("location : 网址"); ?>

<?php
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');

$var = 'google.com';
header("Location: http://$var");

?> 
于 2013-02-13T05:49:58.857 回答
0
header("Location: http://example.com/newURL.php");
die;

是的,脚本在标头重定向后继续,因此请确保调用die;exit;在您重定向时停止执行。不需要让脚本进入睡眠状态:)。

如何在 PHP 中进行重定向?

于 2017-02-10T17:14:12.643 回答
-1

用例场景:将用户重定向到强制门户,然后启动倒数计时器,在 x 分钟后将他们从阻止列表中注销。

于 2017-10-17T14:32:42.993 回答