PHP定时器:每两秒仅允许用户输入一次

5

我正在编写一个网站,用户可以在上面发布内容。这个功能通过以下的jQuery ajax实现:

    $.ajax({
        type: 'POST',
        url: 'action/post.php',
        data: 'posttext='+posttext+'&imageurl='+imageurl,
        success: function(feedback){
            $('#feedback').val(feedback);
        }
    });

现在我想知道:任何人都可以编写自己的ajax来重复地向网站发布内容。我该如何防止这种情况发生?我确定我需要在post.php中进行某种安全检查 - 我已经听说过http referer,但它可以被修改,所以它并不是非常可信。
此外,我想在post.php中添加一个计时器,以确保来自同一IP地址的帖子每x秒只能发布一次,并且如果在x秒以下发送帖子,则重置计时器(类似于stack overflow在评论中所做的操作)。
有人知道如何保护ajax并设置计时器吗?或者有其他保护发布机制的想法吗?
谢谢!
Dennis

你能进一步阐述吗?UX? - Dennis Hackethal
谢谢。不过,我认为一个计时器会非常有帮助 - 我怎样在php中设置一个计时器? - Dennis Hackethal
如果您不信任用户(或其浏览器)发送未被篡改的引荐者,那么期望ajax保持不被篡改似乎是愚蠢的。从浏览器发送或接收的任何内容都可能被篡改。 - Mr. Llama
从浏览器端来说,你无法防止别人编辑你的代码或绕过某些限制。最明显的选择就是对代码进行最小化/混淆处理。在这种情况下,安全性主要由服务器端来实现。 - elclanrs
我在服务器端正确地转义了它,不用担心。我认为我在注入方面是安全的,但仍然容易受到渗透测试的攻击。 - Dennis Hackethal
显示剩余3条评论
2个回答

1

您最好的方法是将信息存储在数据库中。您可以在表格中有4个字段:

ipAddress, submitDate, postText, imageUrl

提交时,请检查当前IP地址在数据库中是否有条目。如果有,请将该条目的提交日期与当前日期进行比较,如果超过您的阈值,则允许提交。否则,发出错误消息并将用户重定向回去。

然而,这仍然不是绝对可靠的,因为IP地址也可以被欺骗或用户可能隐藏在代理后面。


1
请注意,如果您的用户都来自大学宿舍并且在一个IP地址后面进行NAT,则会阻止两个人同时发布。 - Daniel Moses
我可以使用IP地址和用户代理的组合 - 这样行吗? - Dennis Hackethal
@DMoses 很好的观点。OP明确指出了IP地址,但为了解决这个问题,您可以请求一个电子邮件地址或进行完整的用户登录。大锤子用于大钉子。 - Jeff Lambert
我认为我会采用数据库方法,将IP地址和用户代理保存在列中,然后与每个新请求进行比较。感谢您的帮助! - Dennis Hackethal
@Dennis,拥有一个完整的用户名/密码是你最好的选择。虽然有关于浏览器指纹识别的研究,但我个人不会相信这些方法。 - Jeff Lambert
显示剩余2条评论

1

只需将IP地址和请求时间存储在日志文件中。然后在每个请求上检查日志文件,以查找该IP的存在并比较存储的时间。

这是一个简单的脚本,仅允许在10秒后从相同的IP发出请求:

$waitSeconds = 10;
if (allowRequest($waitSeconds)) {
    // allowed
    echo "Welcome.";
} else {
    // not allowed
    echo "Please wait at least $waitSeconds after your last request.";
}
echo '<hr /><a href="#" onclick="location.reload(true);return false">try again</a>';

function getLastRequestTimeDiff($ip = null, $logFile = null)
{
    if ($ip === null) {
        // no specific ip provided, grab vom $_SERVER array
        $ip = $_SERVER["REMOTE_ADDR"];
    }
    if ($logFile === null) {
        // no specific log file taken
        $logFile = "./lookup.log";
    }
    if (!is_file($logFile)) {
        // touch
        file_put_contents($logFile, serialize(array()));
    }
    // read content
    $logContent = file_get_contents($logFile);
    // unserialize, check manual
    $lookup = unserialize($logContent);
    // default diff (f.e. for first request)
    $diff = 0;
    // current timestamp
    $now = time();
    if (array_key_exists($ip, $lookup)) {
        // we know the ip, retrieve the timestamp and calculate the diff
        $diff = $now - $lookup[$ip];
    }
    // set the new request time
    $lookup[$ip] = $now;
    // serialize the content
    $logContent = serialize($lookup);
    // and write it back to our log file
    file_put_contents($logFile, $logContent);
    // return diff (in seconds)
    return $diff;
}

// encapsulate our function in a more simple function (allow yes/no)
function allowRequest($allowed = 10, $ip = null, $logFile = null)
{
    $timeDiff = getLastRequestTimeDiff($ip, $logFile);
    return $timeDiff >= $allowed;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接