简单防恶意提交处理+session保存机制细节

最近一个活动被人搞,主要频繁提交,把这边的一个表塞了很多恶心数据。

场景为:

手机访问,输入身份证相关信息,接口1~3秒,其它活动相关信息。再提交。

处理方式:

主要加了些验证,如图形和session限制。

因为是手机访问,所以同ip是很有可能的情况,只能做一个大阀值处理,但是阀值不好控制,多了没效果,少了,真实手机用户有问题。所以异常ip需要先确认是不是一些运营商的服务器这些要查查。不是就可以直接封了。再加个简单的session校验,说实在,没啥用。不过一般人是通过电脑才来黑,如果通过运营商(就是手机热点)。同时用代理也有一定几率伪造终端ip,暂时都没有啥太好的方式感觉。

贴代码(yii版本):

<?php
/**
 * 特别注意:
 * 服务器上和本地的类是不同的。本地服务器因为链接问题,所以直接进行reture处理。
 * @author caihaibin
 *
 */
class SubmitTools {
	static function model() {
		return new SubmitTools ();
	}
	/**
	 * 防重复提交校验
	 *
	 * @param string $key
	 *        	特殊项目,自己提供当前用户唯一标志。如:活动id+用户手机号码 (必要时,活动链接也可以)
	 * @param boolean $debug_write_log
	 *        	当为true时,所有通过和不通过都写入到日志
	 * @return boolean 指定时间内的第一次提交,为true,重复提交会抛出异常
	 */
	static function record($key = '', $debug_write_log = false) {
		if (empty ( $key )) {
			$key = 'submit_' . Yii::app ()->session->getSessionID ();
		}
		$result = Yii::app ()->tmpcache->get ( $key );
		if ($result) {
			if ($debug_write_log)
				write_log ( 'mult_submit_error', $key );
			throw new Exception ( '当前用户,10秒内只能提交一次' );
		}
		Yii::app ()->tmpcache->add ( $key, '1', 10 );
		if ($debug_write_log)
			write_log ( 'mult_submit', $key );
		return true;
	}
}

上面这个版本是结合php-redis的版本

因为场景里有个情况叫身份校验延迟,这种情况下,验证码校验后更新了数据,但是在会话结束前是不会写到session的数据源里的。所以用redis,记录提交的标志。不提供的情况下就是session_id,还可以自己拼标志,比如身份证号。

多提供个yii的:

Yii::app ()->tmpcache->add ( $key, '1', 10 );

源码说明:

	/**
	 * Stores a value identified by a key into cache if the cache does not contain this key.
	 * This is the implementation of the method declared in the parent class.
	 *
	 * @param string $key the key identifying the value to be cached
	 * @param string $value the value to be cached
	 * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
	 * @return boolean true if the value is successfully stored into cache, false otherwise
	 */
	protected function addValue($key,$value,$expire)
	{
		if ($expire == 0)
			return (bool)$this->executeCommand('SETNX',array($key,$value));

		if($this->executeCommand('SETNX',array($key,$value)))
		{
			$this->executeCommand('EXPIRE',array($key,$expire));
			return true;
		}
		else
			return false;
	}

储存标记是原来有的,则不进行覆盖。同时yii其它cache方式如file也有相应处理。

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注