标头重定向后会执行 PHP 脚本吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14847010/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Will PHP script be executed after header redirect?
提问by user1032531
Yes, this question has been asked before, however, the answers have been inconsistent. Take Why I have to call 'exit' after redirection through header('Location..') in PHP?for instance. Every answer (including the accepted answer) states yes, except the last answer which received zero votes which says "maybe". I am starting to think the correct answer is "maybe". To make it a simple "yes" or "no" question, will doThis() be executed given the following script? Thanks
是的,这个问题以前有人问过,但是,答案不一致。就拿我为什么要通过在PHP头(“位置..”)重定向后打电话到“退出”?例如。每个答案(包括已接受的答案)都表示是,除了最后一个答案获得零票表示“可能”。我开始认为正确的答案是“也许”。为了使它成为一个简单的“是”或“否”问题,在给定以下脚本的情况下会执行 doThis() 吗?谢谢
header('Location: http://somewhereElse.com');
//die();
sleep(1000);
doThis();
EDIT Thanks, all. With my PHP/Linux/Apache configuration, the second syslog() executes, so the answer is "yes, all script down stream of the header will be executed." I will assume (and hope I am correct) it is the same with all PHP/Linux/Apache configurations!
编辑谢谢,大家。使用我的 PHP/Linux/Apache 配置,第二个 syslog() 执行,所以答案是“是的,标题下游的所有脚本都将被执行。” 我会假设(并希望我是正确的)它与所有 PHP/Linux/Apache 配置相同!
<?php
header('Location: http://google.com');
syslog(LOG_INFO,'first');
sleep(5);
syslog(LOG_INFO,'Second');
?>
采纳答案by Cody A. Ray
Yes, the script continues to process after the call to header('Location: http://google.com')if you don't explicitly terminate it! I just tried this locally. I added test.php to a site in apache with these contents:
是的,header('Location: http://google.com')如果您没有明确终止脚本,脚本会在调用后继续处理!我只是在本地尝试过这个。我将 test.php 添加到具有以下内容的 apache 站点:
<?php
header('Location: http://google.com');
error_log("WE MADE IT HERE SOMEHOW");
?>
And checked my /var/log/apache2/error_log for this entry:
并检查了我的 /var/log/apache2/error_log 这个条目:
[Tue Feb 12 23:39:23 2013] [error] [client 127.0.0.1] WE MADE IT HERE SOMEHOW
Possibly surprising, but yes, it continues to execute if you don't halt execution.
可能令人惊讶,但是是的,如果您不停止执行,它会继续执行。
回答by Neo
People seem to get this really confused, and as to why the script is executed. When you send the redirect header the browser immediately redirects the user to the new page but your server will continue to process the code even though there is no one to receive it at the end, this doesn't mean the script is terminated. Unless you configure Apache to stop the script when it realizes there is no one on the other end.
人们似乎对此非常困惑,以及为什么要执行脚本。当您发送重定向标头时,浏览器会立即将用户重定向到新页面,但您的服务器将继续处理代码,即使最后没有人收到它,这并不意味着脚本已终止。除非您将 Apache 配置为在意识到另一端没有脚本时停止脚本。
When a PHP script is running normally the NORMAL state, is active. If the remote client disconnects the ABORTED state flag is turned on. A remote client disconnect is usually caused by the user hitting his STOP button.
当 PHP 脚本正常运行时,NORMAL 状态处于活动状态。如果远程客户端断开连接,则 ABORTED 状态标志将打开。远程客户端断开连接通常是由用户点击他的 STOP 按钮引起的。
You can decide whether or not you want a client disconnect to cause your script to be aborted. Sometimes it is handy to always have your scripts run to completion even if there is no remote browser receiving the output. The default behaviour is however for your script to be aborted when the remote client disconnects. This behavior can be set via the
ignore_user_abortphp.ini directive as well as through the corresponding php_valueignore_user_abortApache httpd.conf directive or with theignore_user_abort()function.
您可以决定是否希望客户端断开连接导致脚本中止。有时,即使没有远程浏览器接收输出,始终让脚本运行完成也很方便。但是,默认行为是在远程客户端断开连接时中止您的脚本。这种行为可以通过
ignore_user_abortphp.ini 指令以及相应的 php_valueignore_user_abortApache httpd.conf 指令或ignore_user_abort()函数来设置。
The correct way of redirecting a user without further actions is:
在没有进一步操作的情况下重定向用户的正确方法是:
header("Location: blah.php");
exit();
回答by Dipesh Parmar
Let me explain more. let's have an example using session.
让我再解释一下。让我们举一个使用 session 的例子。
$_SESSION["username"] = 'some username';
header("Location: another-file.php");
$_SESSION["username"] = 'replace username';
Result of $_SESSION["username"]will be replace username
结果$_SESSION["username"]将是replace username
You can output a lot more headers than just Locationheaders with header, most of which you don't want to stop your code execution. If you want to stop code execution, you need to call exitexplicitly.
您可以输出更多的标头,而不仅仅是Location带有标头的标头,其中大部分是您不想停止代码执行的。如果要停止代码执行,则需要exit显式调用。
The headercommand doesn't interrupt the flow of your code. Even if that is encountered, your page is still downloaded by the browser, even if it isn't show. Consider 404 pages, which (despite being errors) are still processed by the browser (though they are rendered while redirects are not).
该header命令不会中断您的代码流。即使遇到这种情况,您的页面仍会被浏览器下载,即使它没有显示。考虑404 pages,其中(尽管是错误)仍由浏览器处理(尽管它们在重定向时未呈现)。
回答by Jon
Running the code:
运行代码:
//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);
The server paused and wrote the file before the client redirected me. This is because, even after flush()ing the buffer, the the redirect is not processed until the script ceases execution (ie, the script terminated). The file test.txthad '1' in every case, meaning that the headers were sent, just not processed by the browser until the connection was terminated.
在客户端重定向我之前,服务器暂停并写入文件。这是因为,即使在flush()缓冲区之后,重定向也不会被处理,直到脚本停止执行(即脚本终止)。该文件在每种情况下test.txt都有 '1' ,这意味着发送了标头,只是在连接终止之前浏览器不处理。
- in every case, meaning on a win32 development machine, linux development machine, and a linux production environment.
- 在任何情况下,都意味着在 win32 开发机器、linux 开发机器和 linux 生产环境上。
回答by Thoracius Appotite
This first example shows that some code is executed after the header location redirect, but that not all code is necessarily executed. Once the browser starts responding to the redirect header, it'll terminate the connection on the current page, which will causes PHP to terminate executing its code. This shows how NOT to do things.
第一个示例显示在标头位置重定向之后执行了一些代码,但并非所有代码都必须执行。一旦浏览器开始响应重定向标头,它将终止当前页面上的连接,这将导致 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
In this example I added ignore_user_abort() to show how to execute all the code:
在这个例子中,我添加了 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!
And this is how you would typically execute a redirect, by killing the script immediately after the redirect:
这就是通常执行重定向的方式,在重定向后立即终止脚本:
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
In short, either use die(), exit(), or ignore_user_abort(TRUE);
简而言之,要么使用 die()、exit() 或 ignore_user_abort(TRUE);
回答by Andrew
header("Location: http://example.com/newURL.php");
die;
Yes the script continues after the header redirect, so make sure to call die;or exit;any time you you redirect to stop execution. Don't need to put the script to sleep :).
是的,脚本会在标头重定向后继续,因此请确保在重定向时调用die;或exit;以停止执行。不需要让脚本进入睡眠状态:)。
回答by Andrew
yes yes yes, header is like any other part of the php script, it will be sent after the script execution completed, however, the trick is: if we want to redirect to new URL: then why continue executing scripts after header("location: url"); ?>
yes yes yes, 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");
?>
回答by Techie
Yes, it will be executed for short amount of time.
是的,它将在短时间内执行。
Once the redirect header is sent to the browser, the browser will close the current connection and open a new one for the redirect URL. Until that original connection is closed and Apache shuts down the script, your code will continue to execute as before.
In theory, if there was a sufficiently fast connection between the client/server, and there was no buffering anywhere in the pipeline, issuing the header would cause the script to be terminated immediately. In reality, it can be anywhere between "now" and "never" for the shutdown to be initiated.
一旦重定向头被发送到浏览器,浏览器将关闭当前连接并为重定向 URL 打开一个新连接。在原始连接关闭并且 Apache 关闭脚本之前,您的代码将像以前一样继续执行。
理论上,如果客户端/服务器之间的连接速度足够快,并且管道中的任何地方都没有缓冲,则发出标头将导致脚本立即终止。实际上,启动关闭的时间可以介于“现在”和“从不”之间。
回答by linoskoczek
The script will still run after the redirection is done. Although it may be useful sometimes, people who use headerfunction have to be aware, that it can be dangerous. Look at this piece of very unsafe code:
重定向完成后,脚本仍将运行。虽然它有时可能很有用,但使用header函数的人必须意识到它可能是危险的。看这段很不安全的代码:
<?php
if($_GET['some_secret'] != '123') {
setcookie("status", "not logged in");
header("Location: /");
}
setcookie("status", "logged in");
echo("Some secret info!")
?>
No matter what some_secretyou enter, you will always have a cookie with value logged in. The only difference here is that the user will be redirected if wrong parameter value is given.
不管是什么some_secret你进入,你将永远有一个cookie与价值登录。这里唯一的区别是如果给定的参数值错误,用户将被重定向。
Solution: Use die()or exit()method to end the script immediately after redirection
解决方法:使用die()或exit()方法重定向后立即结束脚本
This small correction will make our script working as we wanted to.
这个小的修正将使我们的脚本按我们想要的方式工作。
<?php
if($_GET['some_secret'] != '123') {
setcookie("status", "not logged in");
header("Location: /");
die();
}
setcookie("status", "logged in");
echo("Some secret info!")
?>
(I won't show another simple solution with elsestatement, as this is not really the way it should be done.)
(我不会用else语句展示另一个简单的解决方案,因为这不是真正应该完成的方式。)
You may think, that a user at least won't see the secret information you print on the screen. WRONG!Browser just makes a redirection, but it's up to us if we follow it.
您可能认为,用户至少不会在屏幕上看到您打印的机密信息。错误的!浏览器只是进行重定向,但我们是否遵循它取决于我们。
In this example, I used a vulnerable code without die:
在这个例子中,我使用了一个没有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.
As you can see, secret information leaked.
如您所见,机密信息泄露。
So, be aware, that headercan be very unsafe!
...and remember to normally not store such data like passwords in plaintext or information like logged in in cookies
所以,请注意,这header可能非常不安全!
...并记住通常不要以明文形式存储诸如密码之类的数据或诸如登录 cookie 之类的信息
回答by Dudus
USECASE SCENARIO: Redirect users to captive portal then start a countdown timer to write them off the block list after x minutes.
用例场景:将用户重定向到强制门户,然后启动倒数计时器以在 x 分钟后将其从阻止列表中注销。

