PHP简单的手机验证码验证过程
做过一个需求:广告主后台发起调查活动,普通用户参加此调查后跳转值某个网址领取1Q点(1角钱);上线一段时间以后,广告主反馈得到的很多手机号都是伪造的(我们开始只用正则匹配判断手机号正确与否),然后产品让我们加上手机短信验证,就变成了下面的样子.
刚开始的思路应该很正常的那种,用rand生成随机码,然后存在redis里边,设置expire为60秒;后来考虑考虑,用户为了1角钱不至于如此,需要验证码的时候也不会瞎填写,系统还限制某ID用户明天每天只能参加5次这种活动,也为了不浪费系统资源的原则,公司发的短信已经需要2分钱一条,决定不用redis,用下面的思路:
用用户帐号+活动ID+手机号进行处理生成一个固定的数字,然后驾驶时间戳进行干扰生成4位数的数字,干扰以后只保证4位数对应的二进制的1、5、6、7、8、9位不被干扰,这样对应会生出pow(2,6)个不一样的4位数字,随机发送给用户一个。
用户验证验证码时候也只验证验证码的1、5、6、7、8、9位是否正确,为用户帐号+活动ID+手机号进行处理生成,这样就不用存储验证码,达到验证手机号的号码。
具体的测试例子在下面,为啥说是测试例子呢,因为最后还没有用,我就去封闭开发其他项目去了,下面代码也是偶尔翻到,看代码竟然是我工作一周年的时候写的 ,测试的代码生成的验证码散列的不是很好,也没有时间进行改善,主要介绍一下上面的思路。
<?php/** * * User: shikiliu * Date: 13-7-11 */class TelephoneCheck{ /** * 取得某个用户某次活动的手机验证码 * @param $uin 用户ID 小于10000系统保留 * @param $actId 活动ID 小于1000系统保留 * @param $telephone 用户手机号 * @return bool|int 4位数的验证码 */ public function getTelephoneCode($uin, $actId, $telephone) { if ($uin < 10000 || $actId < 1000 || empty($telephone)) { return false; } $time = time(); $timeFeature = hexdec(substr(md5($time), 0, 3)) & 0x1F1; $telephoneFeature = hexdec(substr(md5($telephone), 8, 4)); $actIdFeature = hexdec(substr(md5($actId), 16, 4)); $uinFeature = hexdec(substr(md5($uin), 24, 4)); $sumFeature = $telephoneFeature + $actIdFeature + $uinFeature; $sumFeature = $sumFeature % 10000; if ($sumFeature < 1000) { $sumFeature = 5145; } $result = $sumFeature | $timeFeature; return $result; } /** * 验证用户的手机验证码 * @param $uin 用户ID 小于10000系统保留 * @param $actId 活动ID 小于1000系统保留 * @param $telephone 用户手机号 * @param $code getTelephoneCode生成的验证码 * @return bool 是否正确 */ public function checkTelephoneCode($uin, $actId, $telephone, $code) { if ($uin < 10000 || $actId < 1000 || empty($telephone) || empty($code)) { return false; } $telephoneFeature = hexdec(substr(md5($telephone), 8, 4)); $actIdFeature = hexdec(substr(md5($actId), 16, 4)); $uinFeature = hexdec(substr(md5($uin), 24, 4)); $sumFeature = $telephoneFeature + $actIdFeature + $uinFeature; $sumFeature = $sumFeature % 10000; if ($sumFeature < 1000) { $sumFeature = 5145; } $sumFeature = $sumFeature & 0xE0E; $code = $code & 0xE0E; if ($sumFeature == $code) { return true; } return false; }}$actId = 10001;$telephone = 13797025562;$uin = 514540767;$telCode = new TelephoneCheck();$code = $telCode->getTelephoneCode($uin, $actId, $telephone);var_dump($code);var_dump($telCode->checkTelephoneCode($uin, $actId, $telephone, $code));var_dump($telCode->checkTelephoneCode($uin, $actId, $telephone, $code+10));