Thinkphp實(shí)現(xiàn)短信驗(yàn)證注冊(cè)功能
前言
注冊(cè)時(shí)經(jīng)常需要用到短信驗(yàn)證碼,本文記錄一下思路和具體實(shí)現(xiàn)。
短信驗(yàn)證平臺(tái)使用云片,短信驗(yàn)證碼的生成使用thinkphp。
思路
1、用戶輸入手機(jī)號(hào),請(qǐng)求獲取短信驗(yàn)證碼。
2、thinkphp生成短信驗(yàn)證碼,存儲(chǔ),同時(shí)和其他參數(shù)一起發(fā)送請(qǐng)求給云片。
3、云片發(fā)送短信驗(yàn)證碼到指定手機(jī)號(hào)。
4、用戶輸入短信驗(yàn)證碼。
5、thinkphp根據(jù)驗(yàn)證碼是否正確、驗(yàn)證碼是否過(guò)期兩個(gè)條件判斷是否驗(yàn)證通過(guò)。
代碼實(shí)現(xiàn)
驗(yàn)證接口
接口地址:https://sms.yunpian.com/v1/sms/send.json。
使用postman,輸入三個(gè)必須的參數(shù)apikey、mobile和text。

php發(fā)起http/https請(qǐng)求
使用php的curl函數(shù)發(fā)起https請(qǐng)求,帶入?yún)?shù)apikey、mobile和text。
// 獲取短信驗(yàn)證碼
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' => '【小太陽(yáng)】您的驗(yàn)證碼是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默認(rèn)不支持https協(xié)議,設(shè)置不驗(yàn)證協(xié)議
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;
}
生成隨機(jī)短信驗(yàn)證碼
默認(rèn)生成四位的隨機(jī)短信驗(yàn)證碼。
// 生成短信驗(yàn)證碼
public function createSMSCode($length = 4){
$min = pow(10 , ($length - 1));
$max = pow(10, $length) - 1;
return rand($min, $max);
}
整合
在數(shù)據(jù)庫(kù)新建表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代碼:
// 獲取短信驗(yàn)證碼
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' => '【小太陽(yáng)】您的驗(yàn)證碼是'.$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); //不驗(yàn)證證書下同
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'=> '創(chuàng)建成功',
'obj'=>$smscode_temp
);
echo json_encode($result,JSON_UNESCAPED_UNICODE);
}
}
}
}
}
驗(yàn)證短信驗(yàn)證碼
驗(yàn)證短信驗(yàn)證碼時(shí)間是否過(guò)期,驗(yàn)證短信驗(yàn)證碼是否正確。
// 驗(yàn)證短信驗(yàn)證碼是否有效
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' => '驗(yàn)證碼過(guò)期,請(qǐng)刷新后重新獲取'
);
echo json_encode($result,JSON_UNESCAPED_UNICODE);
return;
}
if($code != $recordCode){
$result = array(
'code' => '2',
'ext' => '驗(yàn)證碼錯(cuò)誤,請(qǐng)重新輸入'
);
echo json_encode($result,JSON_UNESCAPED_UNICODE);
return;
}
$result = array(
'code' => '0',
'ext' => '驗(yàn)證通過(guò)'
);
echo json_encode($result,JSON_UNESCAPED_UNICODE);
}
}
// 驗(yàn)證驗(yàn)證碼時(shí)間是否過(guò)期
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;
}
}
改進(jìn)
為了防止短信轟炸,在請(qǐng)求獲取短信驗(yàn)證碼時(shí),需要加入圖片驗(yàn)證碼。
thinkphp提供了生成圖片驗(yàn)證碼的函數(shù),下面我們來(lái)實(shí)現(xiàn)驗(yàn)證碼的生成、刷新和驗(yàn)證。
生成和刷新圖片驗(yàn)證碼
// 獲取圖片驗(yàn)證碼,刷新圖片驗(yàn)證碼
public function getPicCode(){
$config = array(
'fontSize'=>30, // 驗(yàn)證碼字體大小
'length'=>4, // 驗(yàn)證碼位數(shù)
'useNoise'=>false, // 關(guān)閉驗(yàn)證碼雜點(diǎn)
'expire'=>600
);
$Verify = new \Think\Verify($config);
$Verify->entry(2333);//2333是驗(yàn)證碼標(biāo)志
}
假設(shè),該函數(shù)的對(duì)應(yīng)url為http://localhost/owner-bd/index.php/Home/CheckCode/getPicCode,那么,圖片驗(yàn)證碼的地址就是這個(gè)url,放入頁(yè)面圖片標(biāo)簽的src屬性即可。
驗(yàn)證圖片驗(yàn)證碼
// 驗(yàn)證驗(yàn)證碼是否正確
public function checkPicCode($code){
$verify = new \Think\Verify();
if($verify->check($code, 2333)){
$result = array(
'code' => '0',
'ext' => '驗(yàn)證通過(guò)'
);
echo json_encode($result,JSON_UNESCAPED_UNICODE);
}else{
$result = array(
'code' => '1',
'ext' => '驗(yàn)證碼錯(cuò)誤,請(qǐng)重新輸入'
);
echo json_encode($result,JSON_UNESCAPED_UNICODE);
};
}
以上方法,我們利用了thinkphp提供的check方法,實(shí)現(xiàn)起來(lái)很簡(jiǎn)單。但是,如果想要得到驗(yàn)證細(xì)節(jié),就沒(méi)有辦法了。比如,驗(yàn)證碼錯(cuò)誤,可能驗(yàn)證碼超時(shí),可能因?yàn)檩斎腧?yàn)證碼錯(cuò)誤,可能因?yàn)轵?yàn)證碼已經(jīng)使用過(guò)等等。必要的時(shí)候,可以重寫thinkphp的驗(yàn)證碼類,或者重寫thinkphp的check方法。
跑通前后端
后端修改
驗(yàn)證圖片驗(yàn)證碼函數(shù),改為被調(diào)用函數(shù):
public function checkPicCode($picCode){
$verify = new \Think\Verify();
if($verify->check($picCode, 2333)){
return true;
}else{
return false;
};
}
在獲取短信驗(yàn)證碼函數(shù)的最頂部,添加調(diào)用圖片驗(yàn)證碼函數(shù),只有通過(guò)驗(yàn)證,才發(fā)送請(qǐng)求給云片。
// 獲取短信驗(yàn)證碼
public function getSMSCode(){
$picCode = $_POST['picCode'];
if(!$this->checkPicCode($picCode)){
$result = array(
'code' => '1',
'ext' => '驗(yàn)證碼錯(cuò)誤,請(qǐng)重新輸入'
);
echo json_encode($result,JSON_UNESCAPED_UNICODE);
return;
}
/*省略*/
}
前端核心代碼
<!--register.html-->
<!DOCTYPE html>
<html lang="zh" ng-app="sunApp">
<head>
<meta charset="UTF-8">
<title>注冊(cè)</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="手機(jī)號(hào)">
</div>
<div class="input-group">
<input type="text" class="pic-code" ng-model="picCode" placeholder="圖片驗(yàn)證碼">
<img class="img" src="{{picCodeUrl}}" alt="" ng-click="refresh()">
</div>
<div class="input-group">
<input type="text" class="sms-code" ng-model="SMSCode" placeholder="短信驗(yàn)證碼">
<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="手機(jī)號(hào)" disabled="true">
</div>
<div class="input-group">
<input type="password" class="password" ng-model="password" placeholder="請(qǐng)輸入密碼">
<input type="password" class="password" ng-model="password2" placeholder="請(qǐng)?jiān)俅屋斎朊艽a">
</div>
<button class="confirm-btn" ng-click="getSMSCode()">注冊(cè)</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 = '獲取驗(yàn)證碼';
$scope.btnSMSDisabled = false;
$scope.checkOver = false;
// 獲取短信驗(yàn)證碼
$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);
});
}
// 驗(yàn)證短信驗(yàn)證碼
$scope.next = function(){
if(!$scope.checkOver){
console.log('未通過(guò)驗(yàn)證');
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);
});
}
// 刷新圖片驗(yàn)證碼
$scope.refresh = function(){
$scope.picCodeUrl = '/owner-bd/index.php/Home/CheckCode/getPicCode?'+Math.random();
}
});
優(yōu)化
以上代碼,安全性不是很好,我們可以利用工具繞過(guò)前端驗(yàn)證。為了避免這個(gè)問(wèn)題,可以在checkPicCode和checkSMSCode函數(shù)中添加session值來(lái)標(biāo)記。
$_SESSION['checkPicCode'] = true; $_SESSION['checkSMSCode'] = true;
在最后一步,向數(shù)據(jù)庫(kù)中添加用戶時(shí),先驗(yàn)證一下兩個(gè)session值是否都為true,都為true時(shí)再添加。
成果

后記
以后也許有用的代碼:
echo json_encode($_SESSION);// 打印出session中的數(shù)據(jù) echo session_id();// 打印當(dāng)前session的id
以上所述是小編給大家介紹的Thinkphp實(shí)現(xiàn)短信驗(yàn)證注冊(cè),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- thinkPHP3.2.3實(shí)現(xiàn)阿里大于短信驗(yàn)證的方法
- ThinkPHP驗(yàn)證碼使用簡(jiǎn)明教程
- thinkphp驗(yàn)證碼顯示不出來(lái)的解決方法
- thinkPHP中驗(yàn)證碼的簡(jiǎn)單使用方法
- thinkphp3.2點(diǎn)擊刷新生成驗(yàn)證碼
- 詳解ThinkPHP3.2.3驗(yàn)證碼顯示、刷新、校驗(yàn)
- thinkphp自帶驗(yàn)證碼全面解析
- ThinkPHP驗(yàn)證碼和分頁(yè)實(shí)例教程
- ThinkPHP3.2.1圖片驗(yàn)證碼實(shí)現(xiàn)方法
- thinkPHP框架實(shí)現(xiàn)的短信接口驗(yàn)證碼功能示例
相關(guān)文章
php中g(shù)et_headers函數(shù)的作用及用法的詳細(xì)介紹
本篇文章介紹了,在php中g(shù)et_headers函數(shù)的作用及用法。需要的朋友參考下2013-04-04
PHP中使用socket方式GET、POST數(shù)據(jù)實(shí)例
這篇文章主要介紹了PHP中使用socket方式GET、POST數(shù)據(jù)實(shí)例,本文分別給出GET方式和POST方式的代碼實(shí)例,需要的朋友可以參考下2015-04-04
PHP實(shí)現(xiàn)的帶超時(shí)功能get_headers函數(shù)
這篇文章主要介紹了PHP實(shí)現(xiàn)的帶超時(shí)功能的get_headers函數(shù),本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-02-02
php中is_null,empty,isset,unset 的區(qū)別詳細(xì)介紹
本篇文章介紹了,php中is_null,empty,isset,unset 的區(qū)別詳細(xì)分析。需要的朋友參考下2013-04-04
ThinkPHP驗(yàn)證碼和分頁(yè)實(shí)例教程
這篇文章主要介紹了ThinkPHP驗(yàn)證碼和分頁(yè)實(shí)例教程,是ThinkPHP中常見的應(yīng)用,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-08-08
在Yii2特定頁(yè)面如何禁用調(diào)試工具欄Debug Toolbar詳解
這篇文章主要給大家介紹了關(guān)于在Yii2特定頁(yè)面如何禁用調(diào)試工具欄Debug Toolbar的相關(guān)資料,文中通過(guò)詳細(xì)的示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-08-08

