關於:「透過限制每分鐘 30 次查詢來降低全面暴力攻擊的機率。」
實際上並非如此 - 攻擊者可以發出 100 個請求。每個請求可能需要 2 秒,但這並不會阻止請求的數量。您需要阻止每 2 秒處理多個請求,而不是在每次執行時延遲 2 秒。
(PHP 4, PHP 5, PHP 7, PHP 8)
sleep — 延遲執行
延遲程式執行指定的 秒數
。
備註:
若要延遲程式執行一小段時間,請使用 usleep(),因為 sleep() 函式需要一個 int 型態的參數。例如,
sleep(0.25)
只會暫停程式執行0
秒。
seconds
停止執行的時間,以秒為單位(必須大於或等於 0
)。
成功則返回零。
如果呼叫被訊號中斷,sleep() 會返回一個非零值。在 Windows 上,此值永遠是 192
(Windows API 中 WAIT_IO_COMPLETION
常數的值)。在其他平台上,傳回值將是剩餘的睡眠秒數。
如果指定的 seconds
為負數,此函式會拋出 ValueError 例外。
版本 | 說明 |
---|---|
8.0.0 | 當 seconds 為負數時,此函式會拋出 ValueError 例外;先前版本則會產生 E_WARNING 警告,並返回 false 。 |
範例 #1 sleep() 範例
<?php
// 目前時間
echo date('h:i:s') . "\n";
// 睡眠 10 秒
sleep(10);
// 醒來!
echo date('h:i:s') . "\n";
?>
此範例將輸出(10 秒後)
05:31:23 05:31:33
關於:「透過限制每分鐘 30 次查詢來降低全面暴力攻擊的機率。」
實際上並非如此 - 攻擊者可以發出 100 個請求。每個請求可能需要 2 秒,但這並不會阻止請求的數量。您需要阻止每 2 秒處理多個請求,而不是在每次執行時延遲 2 秒。
注意:`set_time_limit()` 函式和 `max_execution_time` 設定指令只會影響程式碼本身的執行時間。任何在程式碼執行之外發生的活動所花費的時間,例如使用 `system()` 的系統呼叫、`sleep()` 函式、資料庫查詢等,都不會被計入腳本已執行的最長時間。
為了避免使用在每個作業系統上都無法正常運作的 `usleep` 函式,以下是一個應該具有相同行為的函式
function wait(int $millisecond = 0) {
if (0 !== $millisecond) {
$seconds = (int) ($millisecond / 1000);
$nanoSeconds = ($millisecond % 1000) * 1000000;
time_nanosleep($seconds, $nanoSeconds);
}
}
你應該在成功和失敗的分支中都放入 `sleep`,因為攻擊者可以檢查回應是否緩慢,並將其作為指標 - 縮短延遲時間。但在兩個分支中都加入延遲可以消除這種可能性。
也許很明顯,但這是我使用小數秒來延遲程式碼執行的函式(例如模擬 `sleep(1.5)`)
<?php
/**
* 延遲程式碼執行指定的時間。
* @param mixed $time 暫停程式碼執行的時間。可以用整數或小數表示。
* @example msleep(1.5); // 延遲 1.5 秒
* @example msleep(.1); // 延遲 100 毫秒
*/
function msleep($time)
{
usleep($time * 1000000);
}
?>
Diego Andrade 的 `msleep` 函式與 php7 的 `strict_types` 不相容,將 `usleep` 參數轉換為整數即可相容:
usleep((int)($time * 1000000));
使用 `sleep()` 來產生延遲的輸出效果並不是一個好主意,因為
1) 你必須在 `sleep` 之前 `flush()` 輸出
2) 根據你的設定,`flush()` 可能無法一路作用到瀏覽器,因為網路伺服器可能會套用自己的緩衝,或者瀏覽器可能不會渲染它認為不完整的輸出
例如,Netscape 只會顯示完整的行,並且在 </table> 標籤到達之前不會顯示表格的部分
所以,如果你必須等待事件並且不想消耗太多循環,請使用 `sleep`,但不要將它用於愚蠢的延遲輸出效果!
如果你在使用 `sleep()` 和 `usleep()` 時遇到沒有如預期般回應的問題,請查看 `session_write_close()`
如同匿名使用者在評論中所述;
如果 ajax 函式沒有執行 session_write_close(),那麼你的外部頁面就會看起來像是卡住了,而且在新分頁開啟其他頁面也會停頓。
根據我的測試,呼叫 sleep(0); 會造成「執行緒自旋」。
如果能將這一點明確地寫在文件中就好了,因為它很有用。你可以在不讓 CPU 執行緒超載的情況下進行最短的等待。
我寫了一個使用浮點數作為參數的簡單睡眠方法,它也允許你以毫秒(透過小數秒)為單位進行睡眠。
<?php
function sleepFloatSecs($secs) {
$intSecs = intval($secs);
$microSecs = ($secs - $intSecs) * 1000000;
if($intSecs > 0) {
sleep($intSecs);
}
if($microSecs > 0) {
usleep($microSecs);
}
}
?>
在我的機器上測試,它可以完美運作。
<?php
$x = [0.100,0.250,0.5,1.0,1.5,2.0,2.5];
foreach($x as $secs) {
$t = microtime(true);
sleepFloatSecs($secs);
$t = microtime(true) - $t;
echo "$secs \t => \t $t\n";
}
?>
輸出
<?php
0.1 => 0.10017800331116
0.25 => 0.25016593933105
0.5 => 0.50015211105347
1 => 1.0001430511475
1.5 => 1.5003218650818
2 => 2.000167131424
2.5 => 2.5002470016479
?>
以毫秒為參數的睡眠方法
public static function ms_sleep($milliseconds = 0) {
if($milliseconds > 0) {
$test = $milliseconds / 1000;
$seconds = floor($test);
$micro = round(($test - $seconds) * 1000000);
if($seconds > 0) sleep($seconds);
if($micro > 0) usleep($micro);
}
}
一個使用 sleep 以不同間隔運行一組函式的例子。這不能取代多執行緒,但它可以幫助那些想要做一些輕量級操作的人。你不必使用 eval()。它只是用作一個例子。這與運行標準的 1 秒睡眠迴圈不同,因為睡眠時間更長不會消耗那麼多的 CPU。
<?php
// current time
echo date('h:i:s') . "\n";
// Some example functions
function function_a() { echo 'function_a called @ ' . date('h:i:s') . PHP_EOL; }
function function_b() { echo 'function_b called @ ' . date('h:i:s') . PHP_EOL; }
function function_c() { echo 'function_c called @ ' . date('h:i:s') . PHP_EOL; }
// Add some timers (in seconds) with function calls
$sleeptimers = array();
$sleeptimers['5'][0]['func'] = 'function_a();';
$sleeptimers['10'][0]['func'] = 'function_b();';
$sleeptimers['15'][0]['func'] = 'function_c();';
// Process the timers
while(true) {
$currenttime = time();
reset($sleeptimers);
$mintime = key($sleeptimers);
foreach($sleeptimers as $SleepTime => $Jobs) {
foreach($Jobs as $JobIndex => $JobDetail) {
if(!isset($JobDetail['lastrun'])) {
$sleeptimers[$SleepTime][$JobIndex]['lastrun'] = time();
if($SleepTime < $mintime) $mintime = $SleepTime;
} elseif(($currenttime - $JobDetail['lastrun']) >= $SleepTime) {
eval($JobDetail['func']);
$lastrun = time();
$sleeptimers[$SleepTime][$JobIndex]['lastrun'] = $lastrun;
$mysleeptime = $SleepTime - ($currenttime - $lastrun);
if($mysleeptime < 0) $mysleeptime = 0;
if(($currenttime - $JobDetail['lastrun']) < $mintime) $mintime = $mysleeptime; // account for length of time function runs
echo 'Sleep time for function ' . $JobDetail['func'] . ' = ' . $mysleeptime . PHP_EOL;
}
}
}
echo 'Sleeping for ' . $mintime . ' seconds' . PHP_EOL;
sleep($mintime);
}
?>