简体   繁体   English

防止PHP脚本被淹没

[英]Prevent PHP script from being flooded

I want to prevent my script, from being flooded - if user hit F5 it is executing the script every time. 我想阻止我的脚本被淹没 - 如果用户点击F5,它每次都在执行脚本。

I want to prevent from this and allow one script execution per 2 seconds, is there any solution for that? 我想阻止这种情况并允许每2秒执行一次脚本,有什么解决办法吗?

You can use memcache to do this .. 你可以用memcache来做这个..

Simple Demo Script 简单的演示脚本

$memcache = new Memcache ();
$memcache->connect ( 'localhost', 11211 );
$runtime = $memcache->get ( 'floodControl' );

if ((time () - $runtime) < 2) {
    die ( "Die! Die! Die!" );
} 

else {
    echo "Welcome";
    $memcache->set ( "floodControl", time () );
}

This is just a sample code .. there are also other thing to consider such as 这只是一个示例代码..还有其他需要考虑的事情

A. Better IP address detection (Proxy , Tor ) A.更好的IP地址检测(代理,Tor)

B. Current Action B.当前行动

C. Maximum execution per min etc ... C.每分钟最大执行次数等......

D. Ban User after max flood etc D.最大洪水等后禁止用户

EDIT 1 - Improved Version 编辑1 - 改进版本

Usage 用法

$flood = new FloodDetection();
$flood->check();

echo "Welcome" ;

Class

class FloodDetection {
    const HOST = "localhost";
    const PORT = 11211;
    private $memcache;
    private $ipAddress;

    private $timeLimitUser = array (
            "DEFAULT" => 2,
            "CHAT" => 3,
            "LOGIN" => 4 
    );
    private $timeLimitProcess = array (
            "DEFAULT" => 0.1,
            "CHAT" => 1.5,
            "LOGIN" => 0.1 
    );

    function __construct() {
        $this->memcache = new Memcache ();
        $this->memcache->connect ( self::HOST, self::PORT );
    }

    function addUserlimit($key, $time) {
        $this->timeLimitUser [$key] = $time;
    }

    function addProcesslimit($key, $time) {
        $this->timeLimitProcess [$key] = $time;
    }

    public function quickIP() {
        return (empty ( $_SERVER ['HTTP_CLIENT_IP'] ) ? (empty ( $_SERVER ['HTTP_X_FORWARDED_FOR'] ) ? $_SERVER ['REMOTE_ADDR'] : $_SERVER ['HTTP_X_FORWARDED_FOR']) : $_SERVER ['HTTP_CLIENT_IP']);
    }

    public function check($action = "DEFAULT") {
        $ip = $this->quickIP ();
        $ipKey = "flood" . $action . sha1 ( $ip );

        $runtime = $this->memcache->get ( 'floodControl' );
        $iptime = $this->memcache->get ( $ipKey );

        $limitUser = isset ( $this->timeLimitUser [$action] ) ? $this->timeLimitUser [$action] : $this->timeLimitUser ['DEFAULT'];
        $limitProcess = isset ( $this->timeLimitProcess [$action] ) ? $this->timeLimitProcess [$action] : $this->timeLimitProcess ['DEFAULT'];

        if ((microtime ( true ) - $iptime) < $limitUser) {
            print ("Die! Die! Die! $ip") ;
            exit ();
        }

        // Limit All request
        if ((microtime ( true ) - $runtime) < $limitProcess) {
            print ("All of you Die! Die! Die! $ip") ;
            exit ();
        }

        $this->memcache->set ( "floodControl", microtime ( true ) );
        $this->memcache->set ( $ipKey, microtime ( true ) );
    }

}
  1. Store the last execution time of your script in a database or a file. 将脚本的上次执行时间存储在数据库或文件中。
  2. Read from that file/database and compare to the current time. 从该文件/数据库中读取并与当前时间进行比较。
  3. If the difference is under 2 seconds, terminate the script. 如果差异小于2秒,则终止脚本。
  4. Else, continue normally. 否则,继续正常。

you can either use cookies (which can be disabled) so not a very good idea, or you can use store his ip address in the database, so if more then X tries from the same IP address then do not execute the code, just an if else statement, you will need a table with ip addresses time of request, number of tries 你可以使用cookies(可以被禁用)所以不是一个好主意,或者你可以使用他的IP地址存储在数据库中,所以如果更多然后X尝试从相同的IP地址然后不执行代码,只是一个if else语句,您将需要一个具有ip地址请求时间,尝试次数的表

IF you do not want to use databases then you can use the following code 如果您不想使用数据库,则可以使用以下代码

$file = "file.txt";
$file_content = file_get_contents($file);
$fh = fopen($file, 'w') or die("could not open file");
$now = time();
if($now - $file_content > 60){
// your code here
fwrite($fh, $now);
}else{
echo "Try again later";
}
fclose($fh);

but in this case, it won't be for each visitor but rather for all of them (so say user A came and execute the script, user B won't be able to execute it until 60 seconds pass. 但在这种情况下,它不会是每个访问者而是所有访问者(所以说用户A来执行脚本,用户B将无法执行它直到60秒通过。

The best way would be to store the time on serverside. 最好的方法是将时间存储在服务器端。 If you leave the information on client side it would be easy to by pass. 如果您将信息留在客户端,则很容易通过。

I would for example save the timestamp in a table. 我会举例说明将时间戳保存在表格中。 That inputs and checks against spamming your script. 输入和检查垃圾邮件您的脚本。 And would be easy to set tolerence. 并且容易设置容忍度。

使用apc cache或mencache来存储存储到数据库的信息或从文件中读取我相信是时间/资源消耗

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

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