这个博客发评论并没有限制,主要是因为确实没人用,所以我连xss过滤也没做。不过最近还真有脑残的人来这里刷评论攻击了,好吧,重新开启评论限制。
最简单粗暴的解决方案就是根据ip限制同一时间段内的发布个数,比如1分钟一个ip只能发布6个,之后的请求都驳回。
懒的搞redis,我用mysql来记录用户ip请求。首先是以下Service_FrequencyModel核心类(性能优化不考虑):
<?php
class Service_FrequencyModel extends Model_Service{
/*
1. 新记录添加到数据库
2. 添加的同时自动清理超时的数据
3. 提供插如判断接口,插入成功返回true,失败返回false
*/
protected $_timerange;
protected $_userkey;
protected $_count;
function __construct($settings=[
'userkey'=>'test', // 标记
'timerange'=>60, // 时间段长度,单位秒
'count'=>6 // 该时间段内最多多少次
]){
$this->_timerange=(int)$settings['timerange'];
$this->_userkey=''.$settings['userkey'];
$this->_count=(int)$settings['count'];
}
function append(){
$f=new FrequencyModel;
$f->newdel(['now()-create_time>expires']);
$result=$f->newsearch([
'where'=>'userkey=:userkey',
'params'=>['userkey'=>$this->_userkey,],
'limit'=>[0,$this->_count],
]);
if(count($result->_data)>=$this->_count)return false;
$f->newadd([
'userkey'=>$this->_userkey,
'expires'=>$this->_timerange,
'create_time'=>$f->rawsql('now()'),
]);
return true;
}
}
然后在评论的接口处加一个钩子:
$f=new Service_FrequencyModel([
'userkey'=>'Comments|add|'.$_SERVER['REMOTE_ADDR'],
'timerange'=>60,
'count'=>8
]);
if(!$f->append())throw new Exception('服务器繁忙',403);
至于xss问题么,因为内容是直接输出到页面上的,所以输出评论和用户名的时候转义左右尖括号就行了。
收工。
相关文档
随便看看
畅言模块加载中