程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> Thinkphp實現短信驗證注冊功能

Thinkphp實現短信驗證注冊功能

編輯:PHP綜合

前言

注冊時經常需要用到短信驗證碼,本文記錄一下思路和具體實現。

短信驗證平台使用雲片,短信驗證碼的生成使用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。

// 獲取短信驗證碼
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;
}

生成隨機短信驗證碼

默認生成四位的隨機短信驗證碼。

// 生成短信驗證碼
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 = '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);
}
}
}
}
}

驗證短信驗證碼

驗證短信驗證碼時間是否過期,驗證短信驗證碼是否正確。

// 驗證短信驗證碼是否有效
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為http://localhost/owner-bd/index.php/Home/CheckCode/getPicCode,那麼,圖片驗證碼的地址就是這個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()">注冊</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值來標記。

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

在最後一步,向數據庫中添加用戶時,先驗證一下兩個session值是否都為true,都為true時再添加。

成果

後記

以後也許有用的代碼:

echo json_encode($_SESSION);// 打印出session中的數據
echo session_id();// 打印當前session的id

以上所述是小編給大家介紹的Thinkphp實現短信驗證注冊,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對網站的支持!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved