Flood control using Redis

Updated Dani 4 Tallied Votes 405 Views Share

Here is the function that I use here at DaniWeb to manage flood control. It keeps track of how often a specific user or IP address is making a request, and increments a counter. If there have been no requests after 5 minutes, the counter resets to 0. It returns false if the counter reaches more than 10 requests (in that 5 minute period).

Here is what the Codeigniter redis library looks like:

    /**
     * Get cache metadata
     *
     * @param   string  $key    Cache key
     * @return  array
     */
    public function get_metadata($key)
    {
        $value = $this->get($key);

        if ($value !== FALSE)
        {
            return array(
                'expire' => time() + $this->_redis->ttl($key),
                'data' => $value
            );
        }

        return FALSE;
    }




    /**
     * Save cache
     *
     * @param   string  $id Cache ID
     * @param   mixed   $data   Data to save
     * @param   int $ttl    Time to live in seconds
     * @param   bool    $raw    Whether to store the raw value (unused)
     * @return  bool    TRUE on success, FALSE on failure
     */
    public function save($id, $data, $ttl = 60, $raw = FALSE) { ... }



    /**
     * Increment a raw value
     *
     * @param   string  $id Cache ID
     * @param   int $offset Step/value to add
     * @return  mixed   New value on success or FALSE on failure
     */
    public function increment($id, $offset = 1) { ... }
function no_flooding()
{   
    // Load Codeigniter instance
    $CI =& get_instance();

    $flood_hash = 'flood_control';

    // This part is DaniWeb-specific, but you're welcome to use whatever hash key makes the most sense for you
    if (is_logged_in())
    {
        // me() is DaniWeb-specific
        $flood_hash .= ':' . me()->get('id');
    }
    else
    {
        // get_ip_address() is DaniWeb-specific
        $flood_hash .= ':' . get_ip_address();
    }
    
    $flood_control = $CI->cache->redis->get_metadata($flood_hash);
    
    if ($flood_control === false OR (intval($flood_control['expire']) - time() <= 0))
    {
        // Record the request for flood control
        $CI->cache->redis->save($flood_hash, 1, 300);
    }
    else if ($flood_control['data'] >= 10)
    {
        // Flood control is over the rate limit
        return false;
    }
    else
    {
        // Increment
        $CI->cache->redis->increment($flood_hash);
    }

    // Rate limit not hit, proceed as normal
    return true;
}
Dani 4,084 The Queen of DaniWeb Administrator Featured Poster Premium Member

Just to follow up … The code I provided quickly here could easily be implemented with Memcached instead of Redis.

Please also don’t get caught up in the specific syntax I am using, as I’m using Codeigniter 3’s native redis library.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.