Thinkphp实现短信验证注册功能

时间:2021-05-02

前言

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

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

思路

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

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

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

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

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

代码实现

验证接口

接口地址:https://sms.yunpian.com/v1/sms/send.json。

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

php发起http/https请求

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

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 // 获取短信验证码 public function getsmscode(){ // create curl resource $ch = curl_init(); // set url $url = 'https://sms.yunpian.com/v1/sms/send.json'; curl_setopt($ch, curlopt_url, $url); // set param $paramarr = array( 'apikey' => '******', 'mobile' => '******', 'text' => '【小太阳】您的验证码是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; }

生成随机短信验证码

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

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

整合

在数据库新建表sun_smscode:

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 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 = 'https://sms.yunpian.com/v1/sms/send.json'; curl_setopt($ch, curlopt_url, $url); // set param $mobile = $_post['mobile']; $code = $this->createsmscode(); $paramarr = array( 'apikey' => '******', 'mobile' => $mobile, 'text' => '【小太阳】您的验证码是'.$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); } } } } }

验证短信验证码

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

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 // 验证短信验证码是否有效 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提供了生成图片验证码的函数,下面我们来实现验证码的生成、刷新和验证。

生成和刷新图片验证码

? 1 2 3 4 5 6 7 8 9 10 11 // 获取图片验证码,刷新图片验证码 public function getpiccode(){ $config = array( 'fontsize'=>30, // 验证码字体大小 'length'=>4, // 验证码位数 'usenoise'=>false, // 关闭验证码杂点 'expire'=>600 ); $verify = new \think\verify($config); $verify->entry(2333);//2333是验证码标志 }

假设,该函数的对应url为http://localhost/owner-bd/index.php/home/checkcode/getpiccode,那么,图片验证码的地址就是这个url,放入页面图片标签的src属性即可。

验证图片验证码

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // 验证验证码是否正确 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方法。

跑通前后端

后端修改

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

? 1 2 3 4 5 6 7 8 public function checkpiccode($piccode){ $verify = new \think\verify(); if($verify->check($piccode, 2333)){ return true; }else{ return false; }; }

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

? 1 2 3 4 5 6 7 8 9 10 11 12 13 // 获取短信验证码 public function getsmscode(){ $piccode = $_post['piccode']; if(!$this->checkpiccode($piccode)){ $result = array( 'code' => '1', 'ext' => '验证码错误,请重新输入' ); echo json_encode($result,json_unescaped_unicode); return; } }

前端核心代码

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 <!--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()">注册</button> </form> </body> </html> // register.js angular.module('sunapp').controller('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-www-form-urlencoded' }, datatype: 'json', data: $httpparamserializer(param) }).then(function successcallback(response) { console.log(response.data); if(response.data.code == '0'){ $scope.checkover = true; $scope.btnsmsdisabled = true; var time = 60; var timer = null; timer = $interval(function(){ time = time - 1; $scope.btnsmstext = time+'秒'; 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值来标记。

? 1 2 $_session['checkpiccode'] = true; $_session['checksmscode'] = true;

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

成果

后记

以后也许有用的代码:

? 1 2 echo json_encode($_session);// 打印出session中的数据 echo session_id();// 打印当前session的id

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

原文链接:http://www.cnblogs.com/voidking/p/sms-verification-code.html

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章