Thinkphp实现短信验证注册功能

2018-09-07 19:11

阅读:305

  前言

  注册时经常需要用到短信验证码,本文记录一下思路和具体实现。

  短信验证平台使用云片,短信验证码的生成使用thinkphp。

  思路

  1、用户输入手机号,请求获取短信验证码。

  2、thinkphp生成短信验证码,存储,同时和其他参数一起发送请求给云片。

  3、云片发送短信验证码到指定手机号。

  4、用户输入短信验证码。

  5、thinkphp根据验证码是否正确、验证码是否过期两个条件判断是否验证通过。

  代码实现

  验证接口

  接口地址:。

  使用postman,输入三个必须的参数apikey、mobile和text。

  

  php发起http/https请求

  使用php的curl函数发起https请求,带入参数apikey、mobile和text。

   // 获取短信验证码 public function getSMSCode(){ // create curl resource $ch = curl_init(); // set url $url = 【小太阳】您的验证码是1234 ); $param = ; foreach ($paramArr as $key => $value) { $param .= urlencode($key).=.urlencode($value).&; } $param = substr($param, 0, strlen($param)-1); curl_setopt($ch, CURLOPT_POSTFIELDS, $param); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_POST, 1); //curl默认不支持https协议,设置不验证协议 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //return the transfer as a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // $output contains the output string $output = curl_exec($ch); // close curl resource to free up system resources curl_close($ch); echo $output; }

  生成随机短信验证码

  默认生成四位的随机短信验证码。

   // 生成短信验证码 public function createSMSCode($length = 4){ $min = pow(10 , ($length - 1)); $max = pow(10, $length) - 1; return rand($min, $max); }

  整合

  在数据库新建表sun_smscode:

   DROP TABLE IF EXISTS `sun_smscode`; CREATE TABLE `sun_smscode` ( `id` int(8) NOT NULL AUTO_INCREMENT, `mobile` varchar(11) NOT NULL, `code` int(4) NOT NULL, `create_at` datetime NOT NULL, `update_at` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; thinkphp代码: // 获取短信验证码 public function getSMSCode(){ // create curl resource $ch = curl_init(); // set url $url = 【小太阳】您的验证码是.$code ); $param = ; foreach ($paramArr as $key => $value) { $param .= urlencode($key).=.urlencode($value).&; } $param = substr($param, 0, strlen($param)-1); curl_setopt($ch, CURLOPT_POSTFIELDS, $param); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //不验证证书下同 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //return the transfer as a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // $output contains the output string $output = curl_exec($ch); // close curl resource to free up system resources curl_close($ch); //$outputJson = json_decode($output); $outputArr = json_decode($output, true); //echo $outputJson->code; //echo $outputArr[code]; if($outputArr[code] == 0){ $data[mobile] = $mobile; $data[code] = $code; $smscode = D(smscode); $smscodeObj = $smscode->where(mobile=$mobile)->find(); if($smscodeObj){ $data[update_at] = date(Y-m-d H:i:s); $success = $smscode->where(mobile=$mobile)->save($data); if($success !== false){ $result = array( code => 0, ext => 修改成功, obj => $smscodeObj ); } echo json_encode($result,JSON_UNESCAPED_UNICODE); }else{ $data[create_at] = date(Y-m-d H:i:s); $data[update_at] = $data[create_at]; if($smscode->create($data)){ $id = $smscode->add(); if($id){ $smscode_temp = $smscode->where(id=$id)->find(); $result = array( code=> 0, ext=> 创建成功, obj=>$smscode_temp ); echo json_encode($result,JSON_UNESCAPED_UNICODE); } } } } }

  验证短信验证码

  验证短信验证码时间是否过期,验证短信验证码是否正确。

   // 验证短信验证码是否有效 public function checkSMSCode(){ $mobile = $_POST[mobile]; $code = $_POST[code]; $nowTimeStr = date(Y-m-d H:i:s); $smscode = D(smscode); $smscodeObj = $smscode->where(mobile=$mobile)->find(); if($smscodeObj){ $smsCodeTimeStr = $smscodeObj[update_at]; $recordCode = $smscodeObj[code]; $flag = $this->checkTime($nowTimeStr, $smsCodeTimeStr); if(!$flag){ $result = array( code => 1, ext => 验证码过期,请刷新后重新获取 ); echo json_encode($result,JSON_UNESCAPED_UNICODE); return; } if($code != $recordCode){ $result = array( code => 2, ext => 验证码错误,请重新输入 ); echo json_encode($result,JSON_UNESCAPED_UNICODE); return; } $result = array( code => 0, ext => 验证通过 ); echo json_encode($result,JSON_UNESCAPED_UNICODE); } } // 验证验证码时间是否过期 public function checkTime($nowTimeStr,$smsCodeTimeStr){ //$nowTimeStr = 2016-10-15 14:39:59; //$smsCodeTimeStr = 2016-10-15 14:30:00; $nowTime = strtotime($nowTimeStr); $smsCodeTime = strtotime($smsCodeTimeStr); $period = floor(($nowTime-$smsCodeTime)/60); //60s if($period>=0 && $period<=20){ return true; }else{ return false; } }

  改进

  为了防止短信轰炸,在请求获取短信验证码时,需要加入图片验证码。

  thinkphp提供了生成图片验证码的函数,下面我们来实现验证码的生成、刷新和验证。

  生成和刷新图片验证码

   // 获取图片验证码,刷新图片验证码 public function getPicCode(){ $config = array( fontSize=>30, // 验证码字体大小 length=>4, // 验证码位数 useNoise=>false, // 关闭验证码杂点 expire=>600 ); $Verify = new \Think\Verify($config); $Verify->entry(2333);//2333是验证码标志 }

  假设,该函数的对应url为,那么,图片验证码的地址就是这个url,放入页面图片标签的src属性即可。

  验证图片验证码

   // 验证验证码是否正确 public function checkPicCode($code){ $verify = new \Think\Verify(); if($verify->check($code, 2333)){ $result = array( code => 0, ext => 验证通过 ); echo json_encode($result,JSON_UNESCAPED_UNICODE); }else{ $result = array( code => 1, ext => 验证码错误,请重新输入 ); echo json_encode($result,JSON_UNESCAPED_UNICODE); }; }

  以上方法,我们利用了thinkphp提供的check方法,实现起来很简单。但是,如果想要得到验证细节,就没有办法了。比如,验证码错误,可能验证码超时,可能因为输入验证码错误,可能因为验证码已经使用过等等。必要的时候,可以重写thinkphp的验证码类,或者重写thinkphp的check方法。

  跑通前后端

  后端修改

  验证图片验证码函数,改为被调用函数:

   public function checkPicCode($picCode){ $verify = new \Think\Verify(); if($verify->check($picCode, 2333)){ return true; }else{ return false; }; }

  在获取短信验证码函数的最顶部,添加调用图片验证码函数,只有通过验证,才发送请求给云片。

   // 获取短信验证码 public function getSMSCode(){ $picCode = $_POST[picCode]; if(!$this->checkPicCode($picCode)){ $result = array( code => 1, ext => 验证码错误,请重新输入 ); echo json_encode($result,JSON_UNESCAPED_UNICODE); return; } /*省略*/ }

  前端核心代码

   <!--register.html--> <!DOCTYPE html> <html lang=zh ng-app=sunApp> <head> <meta charset=UTF-8> <title>注册</title> </head> <body ng-controller=registerController> <form action= class=register-form ng-show=isShow1> <div class=input-group> <input type=text class=mobile ng-model=mobile placeholder=手机号> </div> <div class=input-group> <input type=text class=pic-code ng-model=picCode placeholder=图片验证码> <img class=img src={{picCodeUrl}} alt= ng-click=refresh()> </div> <div class=input-group> <input type=text class=sms-code ng-model=SMSCode placeholder=短信验证码> <button class=btn-sms ng-click=getSMSCode() ng-disabled=btnSMSDisabled>{{btnSMSText}}</button> </div> <button class=confirm-btn ng-click=next()>下一步</button> </form> <form action= class=register-form ng-show=isShow2> <div class=input-group> <input type=text class=mobile ng-model=mobile placeholder=手机号 disabled=true> </div> <div class=input-group> <input type=password class=password ng-model=password placeholder=请输入密码> <input type=password class=password ng-model=password2 placeholder=请再次输入密码> </div> <button class=confirm-btn ng-click=getSMSCode()>注册troller(registerController, function ($scope,$http,$httpParamSerializer,$state,$interval) { $scope.picCodeUrl = /owner-bd/index.php/Home/CheckCode/getPicCode; $scope.isShow1 = true; $scope.isShow2 = false; $scope.btnSMSText = 获取验证码; $scope.btnSMSDisabled = false; $scope.checkOver = false; // 获取短信验证码 $scope.getSMSCode = function(){ var param = { mobile: $scope.mobile, picCode: $scope.picCode }; $http({ method:POST, url:/owner-bd/index.php/Home/SMS/getSMSCode, //url: /owner-fd/mock/common.json, headers:{ Content-Type:application/x-秒; if(time == 0) { $interval.cancel(timer); $scope.btnSMSDisabled = false; $scope.btnSMSText = 重新获取; } }, 1000); } }, function errorCallback(response) { console.log(response.data); }); } // 验证短信验证码 $scope.next = function(){ if(!$scope.checkOver){ console.log(未通过验证); return; } var param = { mobile: $scope.mobile, code: $scope.SMSCode }; $http({ method:POST, url:/owner-bd/index.php/Home/SMS/checkSMSCode, //url: /owner-fd/mock/common.json, headers:{ Content-Type:application/x-www-form-urlencoded }, dataType: json, data: $httpParamSerializer(param) }).then(function successCallback(response) { console.log(response.data); if(response.data.code == 0){ $scope.isShow1 = false; $scope.isShow2 = true; } }, function errorCallback(response) { console.log(response.data); }); } // 刷新图片验证码 $scope.refresh = function(){ $scope.picCodeUrl = /owner-bd/index.php/Home/CheckCode/getPicCode?+Math.random(); } });

  优化

  以上代码,安全性不是很好,我们可以利用工具绕过前端验证。为了避免这个问题,可以在checkPicCode和checkSMSCode函数中添加session值来标记。

   $_SESSION[checkPicCode] = true; $_SESSION[checkSMSCode] = true;

  在最后一步,向数据库中添加用户时,先验证一下两个session值是否都为true,都为true时再添加。

  成果

  

  后记

  以后也许有用的代码:

   echo json_encode($_SESSION);// 打印出session中的数据 echo session_id();// 打印当前session的id

  以上所述是小编给大家介绍的Thinkphp实现短信验证注册,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!


评论


亲,登录后才可以留言!