首页 > 代码库 > 项目 经验记录(续)

项目 经验记录(续)

此文是之前项目经验的续篇。上篇讲了开发抽奖API遇到的难点及其解决方案,这篇将讲述上线后发生的事情。

抽奖项目上线之后,反响不错,领导还表扬了。但是有一天上午,有个事业部打来电话,说刚刚开始上线的活动,抽奖提示奖品已抽完,叫我们查一下。

活动是百分百中奖的,只有所有奖品库存没有了,才会提示奖品已经抽完。我到redis里面一查,的确奖品没有了。奖品库存存进去的也没错,那是什么原因呢?

(2w 多的奖品在不到两分钟被刷完,我的api处理高并发还是达到要求了)

我们接下来去看此次活动的中奖纪录,发现奖品的确是被抽完了,我们的api本身没问题。接下来从中奖记录中发现,明显有人在刷奖,因为中奖的userid是连着的。也就是有人恶意注册了一批号,来抽奖。从程序逻辑来看,是没有错的。由于此次活动没有门槛,只要是个注册用户就可以抽奖,是有人在利用这个规则而已。没办法,必须杜绝这种现象啊,业务提出,赶紧开发验证码验证吧,避免刷奖。

大概逻辑是这样的:用户点击抽奖的时候,会请求抽奖API,抽奖API返回一个token。客户端接收到这个token之后去请求验证码API,返回验证码。

客户端填写验证码之后,把token和验证码一起请求抽奖API,抽奖API验证通过之后就可以抽奖。

1 第一次请求抽奖API时,随机生成一个token,这个token返回给客户端,客户端会利用这个token去请求验证码生成API。生成验证码算法抽奖API验证时必须知道。也就是token和验证码是一一对应的关系。利用一一对应生成验证码,也利用一一对应验证验证码。(实现了token和验证码的一一对应)

2 简单的token是不行的。比如说,我获取了token后,它的验证码也可以获取,我每次都拿这个token和相对应的验证码去请求抽奖,是可以通过验证的。那我们在token中加入user_id相关信息,那么每个用户的token是不一样的,也就是相同的token不能被同一用户利用。(也就是说token也要验证,验证用户。例如token32位,前15位是user_id加密之后的,每次请求抽奖时会验证user_id对不对)。这样就避免了不同用户利用同一token和验证码抽奖。(实现了不同的用户token不一样)

 

3 不同的抽奖中,用户可以利用上次他的token和验证码抽奖。那么加入时间信息,可以彻底避免这种情况。我们在生成验证码的时候,是利用token生成的,有一个算法,我们在里面salt加入时间戳信息,同一用户的token在不同时刻生成的验证码也不一样。注意这个时间戳我们以一分钟为度,一分钟变一次。(实现了同一用户在不同活动中的验证码生成不一样)。还是存在一点问题,一分钟就过期了,所以用户必须在一分钟中填完验证码,否则验证失效。

 

当然,验证码是不好的用户体验,不到万不得已不要用验证码。还有,在专业的攻击者面前,验证码是小case。君不见12306的验证码么,有什么用。

上面是验证码生成过程中的一些问题。只是为了理解这个原理。

其实我们的验证码上线之后, 过了两天,又被人破解了,人家直接破了验证码,验证码相当于废了。

最后公司有专门的防刷系统,在我们的api中加入防刷api验证,解决了这个问题。当然,这是后话。

 

项目 经验记录(续)