前言
有这样一个场景,用户每天可以领取一个礼品(也可以是其他的东西,反正一天只能领取一次,不能重复领取),在这种情况下,或许有人就会心怀不轨,利用脚本或者其他形式的工具(俗称:外挂)疯狂刷领取礼品的接口,下面就来分析下这个过程。其实这个涉及到安全的问题
正常逻辑
正常写代码的时候业务逻辑,可能是这样的:
1.首先判断该用户领取礼品的标识字段是否为1(也可以是其他,这里只是假定1就是:已领取)
2.如果是1,则已经领取
3.如果是0,则没有领取,可以发放礼品,并将这个标识字段修改成1
那么问题来了,大家仔细想想,如果我疯狂的请求这个过程,是不是会出现,我还没来得及将0修改成1的时候,第二个请求来判断是否是1的时候,这个标识字段还是0(因为还没来得及修改成1),这个时候就出问题,礼品就会发放(其实第一个请求已经发过了),所以这样的处理是有问题的,下面就介绍下解决方法。
解决方法
首先新建一个这样的数据表(我这边已经精简)
CREATE TABLE `gift_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`flag` tinyint(2) DEFAULT NULL,
`uid` int(11) DEFAULT NULL,
`date_time` varchar(20) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我这里模拟了一条数据,仅仅是为了更形象的让大家理解
id flag uid date_time
1 0 1 20160407
方法一
1.首先判断
select flag from gift_log where uid = 1
2.没有发放礼品就再更新
update gift_log set flag = 1 where flag = 0
3.判断影响的行数
如果影响行数为1,表示是从0=>1的过程,如果影响行数是0,表示是从1=>1的过程,只有影响行数是1的才能发放礼品。是不是很赞!
方法二(其实跟方法类似)
1.首先判断是否有记录
select flag from gift_log where uid = 1 and date_time = '20160408'
2.没有发放礼品就再更新
update gift_log set flag = 1,date_time='20160408' where date_time != '20160408'
3.判断影响的行数
如果影响行数为1,才能发放礼品。这个其实跟上面那个原理很相似,只是这个是用日期来做,主要还是看业务上有没有这个需求。