简体   繁体   English

脚本重定向后会执行PHP脚本吗?

[英]Will PHP script be executed after header redirect?

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? 为什么我必须在PHP中通过标题('Location ..')重定向后调用'exit'? 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 谢谢

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." 使用我的PHP / Linux / Apache配置,第二个syslog()执行,所以答案是“是的,将执行标题的所有脚本下游”。 I will assume (and hope I am correct) it is the same with all PHP/Linux/Apache configurations! 我将假设(并希望我是正确的)它与所有PHP / Linux / Apache配置相同!

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

Yes, the script continues to process after the call to header('Location: http://google.com') if you don't explicitly terminate it! 是的,如果您没有明确终止它,脚本会在调用header('Location: http://google.com')后继续处理header('Location: http://google.com') I just tried this locally. 我刚在当地尝试过。 I added test.php to a site in apache with these contents: 我使用以下内容将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. 可能令人惊讶,但是,如果你不停止执行,它会继续执行。

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. 当PHP脚本正常运行时,NORMAL状态处于活动状态。 If the remote client disconnects the ABORTED state flag is turned on. 如果远程客户端断开连接,则打开ABORTED状态标志。 A remote client disconnect is usually caused by the user hitting his STOP button. 远程客户端断开通常是由用户按下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_abort php.ini directive as well as through the corresponding php_value ignore_user_abort Apache httpd.conf directive or with the ignore_user_abort() function. 可以通过ignore_user_abort php.ini指令以及相应的php_value ignore_user_abort Apache httpd.conf指令或ignore_user_abort()函数来设置此行为。

The correct way of redirecting a user without further actions is: 在没有进一步操作的情况下重定向用户的正确方法是:

header("Location: blah.php");
exit();

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 Location headers with header, most of which you don't want to stop your code execution. 您可以输出比带有标题的Location标题更多的标题,其中大多数您不想停止代码执行。 If you want to stop code execution, you need to call exit explicitly. 如果要停止代码执行,则需要显式调用exit

The header command doesn't interrupt the flow of your code. header命令不会中断代码流。 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). 考虑404 pages (尽管是错误的)仍然由浏览器处理(尽管它们是在重定向时不呈现的)。

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). 这是因为,即使在flush()缓冲区之后,也不会处理重定向,直到脚本停止执行(即脚本终止)。 The file test.txt had '1' in every case , meaning that the headers were sent, just not processed by the browser until the connection was terminated. 文件test.txt 在每种情况下都为'1',这意味着标题已被发送,直到连接终止才被浏览器处理。

  • in every case , meaning on a win32 development machine, linux development machine, and a linux production environment. 在每种情况下 ,意味着在win32开发机器,linux开发机器和linux生产环境中。

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. 一旦浏览器开始响应重定向头,它将终止当前页面上的连接,这将导致PHP终止执行其代码。 This shows how NOT to do things. 这表明不怎么做。

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);

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. 将重定向标头发送到浏览器后,浏览器将关闭当前连接并为重定向URL打开一个新连接。 Until that original connection is closed and Apache shuts down the script, your code will continue to execute as before. 在原始连接关闭并且Apache关闭脚本之前,您的代码将继续像以前一样执行。

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. 实际上,它可以在“现在”和“从不”之间的任何地方启动关闭。

Read more 阅读更多

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"); 是的是,标题就像php脚本的任何其他部分一样,它将在脚本执行完成后发送,但是,诀窍是:如果我们想要重定向到新的URL:那么为什么在标题之后继续执行脚本(“location” :url“); ?> ?>

<?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");

?> 
header("Location: http://example.com/newURL.php");
die;

Yes the script continues after the header redirect, so make sure to call die; 是的,脚本重定向后脚本继续,所以一定要调用die; or exit; exit; any time you you redirect to stop execution. 任何时候你重定向停止执行。 Don't need to put the script to sleep :). 不需要让脚本睡觉:)。

How to make a redirect in PHP? 如何在PHP中进行重定向?

The script will still run after the redirection is done. 重定向完成后,该脚本仍将运行。 Although it may be useful sometimes, people who use header function have to be aware, that it can be dangerous. 虽然它有时可能有用,但是使用header功能的人必须意识到它可能是危险的。 Look at this piece of very unsafe code: 看看这段非常不安全的代码:

<?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_secret you enter, you will always have a cookie with value logged in . 无论你输入什么some_secret ,你都会有一个值已登录的cookie。 The only difference here is that the user will be redirected if wrong parameter value is given. 这里唯一的区别是,如果给出错误的参数值,将重定向用户。

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 else statement, 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 header can be very unsafe! 所以,请注意, header可能非常不安全!
...and remember to normally not store such data like passwords in plaintext or information like logged in in cookies ...并且记住通常不会以明文或像登录在cookie中的信息那样存储密码等数据

USECASE SCENARIO:将用户重定向到强制门户,然后启动倒数计时器,在x分钟后将其写入阻止列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM