discuz防灌水机制

    最近论坛频遭灌水机灌水,在不影响用户体验的情况下,需设计一个防灌水机制。以下是本人的方法,能有效防止相当一部分灌水。

1. 由于discuz自带的验证码已被破解,最好另外弄个验证码类,验证码最好是扭曲字体,而且字母与字母间最好能镶嵌,同时有随机连线把字符连起来(曲线和字符都是同种颜色的),这样会大大增加破解验证码的难度;

 

2. 设置关键字过滤(此法会影响发帖速度,注意);

 

3. 发帖内容对比 MD5特征库,与库中记录一致的,则是灌水帖.(MD5特征库是新增数据表,只有一个字段:帖子内容的md5字符)


4. 发帖内容对比自己之前发过的帖子(此处有两个步骤,第一步:截取上次帖子的前N个字符,和这次帖子的前N个字符做对比,假如一致,则是灌水帖;第二步:使用编辑距离算法判断与前一次帖子的相识度,超过设定的阀值则当做灌水帖),如果是灌水帖,则把帖子内容经MD5转换,插入MD5特征库。


5.  成功发布。

 

对于被认为是发灌水帖的用户,可以采取相应的封IP, 禁言等操作。

 

此处仅是抛砖引玉,希望大家分享下还有什么方法能有效防止灌水机。

展开阅读全文

防垃圾信息灌水的智能验证码

02-06

最近系统经常遇到广告机发的垃圾信息攻击。很多人想到的方法是增强验证码的难度,或者做一些问答来防止。但是这样在防止广告机的同时,对正常用户的使用和体验也造成很大困难。这里提供一个智能验证码的思路。rnrn即:在短时间内成功使用验证码后,验证码使用频率记录+1。短时间内下次生成时,将自动增加长度和难度。终极变态验证码就是扭曲的中文即可。rnrn大致代码如下:rn[b]建立一个c_iphistory数据表,用来记录验证码使用频率。[/b]rn[code=sql]CREATE TABLE IF NOT EXISTS `c_iphistory` (rn `id` int(11) NOT NULL AUTO_INCREMENT,rn `ip` varchar(255) NOT NULL,rn `num` int(11) NOT NULL,rn `lastdateline` int(11) NOT NULL,rn PRIMARY KEY (`id`),rn UNIQUE KEY `ip` (`ip`)rn) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='使用验证码的ip对应次数';rn[/code]rnrn[b]生成验证码部分:[/b]rn[code=php]rn$freq = 60;//定义洪水攻击的频率rn //检查是否已存储rn $tmp = db::r("select * from c_iphistory where ip='$_G[ip]'");rn $len = 2;rn $type = 0;rn if($tmp && $tmp['num'] > 0) rn $num = $tmp['num'];rn $timeout = TS - $tmp['lastdateline'];rn $num -= floor($timeout / $freq);//洪水指数降多少级rn if($num < 0) $num = 0;rn $len += $num;rn rnrn if($len > 3)//倍增难度,长度2-5位rn $type = floor($len / 4);rn if($type > 8) rn $type = 8;rn $len -= 34;rn elsern $len = $len % 4;rn $len += 2;rn rn elsern $len += 2;rn rn $secode = s::rrand($len, $type);rn//下面就用$secode生成图片并记录到验证码库中以备验证即可。rnrn//************************函数部分****************************//rn /**rn * 随机数 @zairwolfrn *rn */rn function rrand($len, $type = 7) //1 - Number //2 - Lower Char //4 - Upper Char //8 - Chinesern mt_srand((double)microtime() * 1000000);rn switch($type) rn case 0:rn $charlist = '012';rn break;rn case 1:rn $charlist = '0123456789';rn break;rn case 2:rn $charlist = 'abcdefghijklmnopqrstuvwxyz';rn break;rn case 3:rn $charlist = '0123456789abcdefghijklmnopqrstuvwxyz';rn break;rn case 4:rn $charlist = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';rn break;rn case 5:rn $charlist = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';rn break;rn case 6:rn $charlist = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';rn break;rn case 7:rn $charlist = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';rn break;rn case 8://使用中文rn global $Ccharlist;rn if(!$Ccharlist) $Ccharlist = file_get_contents("lib/disturbTxt.lib");rn break;rn rn $str = '';rn if($type == 8) rn $max = strlen($Ccharlist) / 3-1;rn for($i = 0; $i < $len; $i++) $str .= substr($Ccharlist, mt_rand(0, $max) * 3, 3);rn else rn $max = strlen($charlist) - 1;rn for($i = 0; $i < $len; $i++) $str .= $charlist[mt_rand(0, $max)];rn rn return $str;rn rnrnrn[/code]rnrn[b]验证码验证部分[/b]rn[code=php]rn//在验证码检查确认正确之后,进行如下操作rn$freq = 60;//定义洪水攻击的频率rn //检查是否已存储rn $tmp = db::r("select * from c_iphistory where ip='$ip'");rn if(!$tmp) rn $s = array(rn 'ip' => $ip,rn 'num' => 1,rn 'lastdateline' => TS,rn );rn db::i("insert into c_iphistory set ".sqlcol($s));rn else//更新洪水攻击记录rn $timeout = TS - $tmp['lastdateline'];rn if($timeout > $freq)//超过1分之前发的,已有记录--rn $num = $tmp['num'] - 1;rn if($num < 0) $num = 0;rn $s = array(rn 'num' => $num,rn 'lastdateline' => TS,rn );rn db::q("update c_iphistory set ".sqlcol($s)." where id='$tmp[id]'");rn elsern $num = $tmp['num'] + 1;rn $s = array(rn 'num' => $num,rn 'lastdateline' => TS,rn );rn db::q("update c_iphistory set ".sqlcol($s)." where id='$tmp[id]'");rn rn rnrn[/code]rnrn思路供参考。TS为time()。其它几个地方,估计大家都能看懂。 论坛

discuz的数据库调用机制到底是怎么回事

09-24

[color=#FF0000][size=18px]给100分[/size][/color] rn最近研究discuz,看到官方包中很多htm模板中没有调用数据库的语句,几乎清一色的全是loop循环,这我就有点不明白了, 在调用前没有sql语句出现,循环什么呢?rn但是事实正好相反,它是能调出来的,所以不明白它的调用机制是怎么回事!rnrn为了更好的说明举一个例子吧!rn比如下面这个loop循环:rn[code=html]rn rn rn rn rn rn rn rn ¥ $trade[price]rn rn rn lang additional $trade[credit] $_G[setting][extcredits][$_G['setting']['creditstransextra'][5]][unit]$_G[setting][extcredits][$_G['setting']['creditstransextra'][5]][title]rn rn $trade[subject]rn rn [/code]rnrnloop语法是这样的:If(is_array($abc)) rn Foreach($abc AS $key => $val) rn rnrnrnrn所以上面那段代码中$trades[$tid]肯定是一个数组了,即然是数组,他就是一个数据表的集合,,那么这个表php文件是如何调取的呢,还有就是这个[color=#FF0000]htm模板怎么知道它用的是哪个php里面调取的数据表[/color][size=18px][/size]呢?rn当然有人会说了:discuz的默认包,官方自己写的判断,也许是这样的,可是别忘了,程序要扩展的,如果用户自己写一个表加进去,那怎么办呢?当然了,在htm中写一个sql也是可以的,但是即然官方不这么写,我想它肯定有一个规律在里面,只是官方没有说明罢了!那么这个机制是啥呢?rn希望回答时关键地方要说明,不要清描淡写! 论坛

实在没办法了,来请教一个防灌水的计数器。PHP+MYSQL

07-28

先看代码:rn======================================================================================rnrn 5 )//超过5秒,则计数器+1rn rn $conn=mysql_connect( $mysql_server_name, $mysql_username, $mysql_password );rnrn $sql = "INSERT INTO `counter` ( `name` , `ip_addr` , `at_time` , `new` ) VALUES ('page1','$ip_addr',CURRENT_TIMESTAMP,'1');";rn rn mysql_select_db($mysql_database,$conn);rn rn $result = mysql_query($sql);rn rn rn rn rn $result=mysql_query( "SELECT COUNT(*) FROM `counter` WHERE `name` = 'page1'");rn rn $row=mysql_fetch_row($result);rn rn $page1=$row[0];rn rn mysql_free_result($result);rnrn?>rnrn//前台页面显示开始rn 访问计数:rn======================================================================================rnrnrn其他说明:rn数据库字段中 at_time 的数据类型为TIMESTAMP rnname字段是为了建立多页面计数准备的,当前代码是page1的代码rnrn=======================================================================================rn问题具体陈述:rn目前是这样编写的: rn1.取访问者的ip和数据库里的对比,如果有,执行2;没有,执行3. rn2.计算现在和最近一次访问的时间差,如果大于防灌水时间,执行3;小于,执行4。 rn3.将ip,时间写入数据库(即记录数+1). rn4.读取访问次数,显示在网页上! rn--------------------------- rn其中第2步的数据库操作我是这么写的: rnSELECTTIME_TO_SEC(NOW())-TIME_TO_SEC(time_at)FROM`gbook`WHEREip_at='$ip'ANDuser_name='user1'ORDERBY`TIME_TO_SEC(NOW())-TIME_TO_SEC(time_at)`ASC rn---------------- rn也就是计算现在时间和最近一次访问的相差秒数。 rnrn问题:他只把时间的小时+分+秒进行计算。不管天数,假如你昨天下午访问的,今天上午访问的话,那么减出来的值就是负数。而设置的防灌水时间是正数,所以数据库不记录.............我现在需要他记录。但不知道怎么操作了。 rn望各位高人给点思路~~~ 论坛

没有更多推荐了,返回首页