摘要:前言注冊時經常需要用到短信驗證碼,本文記錄一下思路和具體實現。短信驗證平臺使用云片,短信驗證碼的生成使用。云片發送短信驗證碼到指定手機號。用戶輸入短信驗證碼。
前言
注冊時經常需要用到短信驗證碼,本文記錄一下思路和具體實現。
短信驗證平臺使用云片,短信驗證碼的生成使用thinkphp。
1、用戶輸入手機號,請求獲取短信驗證碼。
2、thinkphp生成短信驗證碼,存儲,同時和其他參數一起發送請求給云片。
3、云片發送短信驗證碼到指定手機號。
4、用戶輸入短信驗證碼。
5、thinkphp根據驗證碼是否正確、驗證碼是否過期兩個條件判斷是否驗證通過。
接口地址:https://sms.yunpian.com/v1/sms/send.json。
使用postman,輸入三個必須的參數apikey、mobile和text。
使用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 ThinkVerify($config); $Verify->entry(2333);//2333是驗證碼標志 }
假設,該函數的對應url為http://localhost/owner-bd/index.php/Home/CheckCode/getPicCode,那么,圖片驗證碼的地址就是這個url,放入頁面圖片標簽的src屬性即可。
驗證圖片驗證碼// 驗證驗證碼是否正確 public function checkPicCode($code){ $verify = new ThinkVerify(); 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 ThinkVerify(); 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.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書簽
云片網
https://www.yunpian.com/
cURL函數
http://php.net/manual/zh/ref....
curl 基礎例子
http://php.net/manual/zh/curl...
在PHP語言中使用JSON
http://www.ruanyifeng.com/blo...
thinkphp驗證碼
http://document.thinkphp.cn/m...
修改ThinkPHP的驗證碼類
http://www.cnblogs.com/BTMast...
ThinkPHP 3.2版本 , 無法讀取$_SESSION["verify_code"]
http://www.cnblogs.com/lovezb...
LICEcap - Download
http://licecap.en.softonic.com/
gif動態圖局部加馬賽克模糊廣告文字
http://www.leawo.cn/space-138...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/21933.html
摘要:本方法基于,用到了,當然具體項目中也可以不用,下面我就按步驟來寫下來。 本方法基于Thinkphp,用到了jquery.validate,當然具體項目中也可以不用,下面我就按步驟來寫下來。 1.準備 1.登陸http://www.alidayu.com,進入網址用淘寶號登陸即可2.進入管理中心 showImg(https://segmentfault.com/img/bVQTOk?w=...
摘要:之前使用的阿里大于,不過很坑的是,新接入的都不能用了,融入進了阿里云服務,當然阿里大于的老用戶還可以繼續用阿里大于首先還是接入,上圖找到短信服務設置短信簽名和短信模板設置或找到或下載文檔打開下載下來的文檔,只需要,將其改名為,并放到項目根目 之前使用的阿里大于,不過很坑的是,新接入的都不能用了,融入進了阿里云服務,當然阿里大于的老用戶還可以繼續用阿里大于 首先還是接入,上圖: (1)找...
閱讀 713·2023-04-25 17:54
閱讀 2971·2021-11-18 10:02
閱讀 1131·2021-09-28 09:35
閱讀 648·2021-09-22 15:18
閱讀 2847·2021-09-03 10:49
閱讀 3050·2021-08-10 09:42
閱讀 2572·2019-08-29 16:24
閱讀 1254·2019-08-29 15:08