thinkphp实现短信验证注册

时间:2022-09-07 17:33:26

前言

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

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

思路

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

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

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

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

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

代码实现

验证接口

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

使用postman,输入三个必须的参数apikeymobiletext

thinkphp实现短信验证注册

php发起http/https请求

使用php的curl函数发起https请求,带入参数apikeymobiletext

// 获取短信验证码
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时再添加。

成果

thinkphp实现短信验证注册

后记

以后也许有用的代码:

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

书签

云片网

https://www.yunpian.com/

cURL函数

http://php.net/manual/zh/ref.curl.php

curl 基础例子

http://php.net/manual/zh/curl.examples.php

在PHP语言中使用JSON

http://www.ruanyifeng.com/blog/2011/01/json_in_php.html

thinkphp验证码

http://document.thinkphp.cn/manual_3_2.html#verify

修改ThinkPHP的验证码类

http://www.cnblogs.com/BTMaster/p/3547878.html

ThinkPHP 3.2版本 , 无法读取$_SESSION['verify_code']

http://www.cnblogs.com/lovezbs/p/4496117.html

LICEcap - Download

http://licecap.en.softonic.com/

gif动态图局部加马赛克模糊广告文字

http://www.leawo.cn/space-138176-do-thread-id-64000.html

thinkphp实现短信验证注册的更多相关文章

  1. java短信验证和注册

    最近公司需要用到短信验证注册,所以申请了阿里云的短信服务.我的项目是分布式的spring boot 原理: 利用第三方发送短信 获取回执消息,然后存入缓存里面 将用户填写的验证码与缓存里面的验证码对比 ...

  2. 基于ThinkPHP与阿里大于的PHP短信验证功能

    https://blog.csdn.net/s371795639/article/details/53381274 PHP阿里大鱼短信验证 第一步 登陆阿里大于注册账号,在用户管理中心创建应用,确定A ...

  3. Luffy之注册认证&lpar;容联云通讯短信验证&rpar;

    用户的注册认证 前端显示注册页面并调整首页头部和登陆页面的注册按钮的链接. 注册页面Register,主要是通过登录页面进行改成而成. 先构造前端页面 <template> <div ...

  4. 注册登录页面修订-Python使用redis-手机验证接口-发送短信验证

    登录页面修订 views.Login.vue <template> <div class="login box"> <img src="@/ ...

  5. PHP阿里大鱼短信验证

    PHP阿里大鱼短信验证 第一步 登陆阿里大于注册账号,在用户管理中心创建应用,确定AppKEY和App Secret还有配置签名 第二步 在应用管理中选择SDK下载,或者直接点击http://down ...

  6. Mob&period;com 短信验证的简单使用

    1.环境配置 http://wiki.sharesdk.cn/android-短信sdk集成文档/ a.sdk下载 http://www.mob.com/#/downloadDetail/SMS/an ...

  7. Mob短信验证的具体使用

    原文著作权地址:http://www.jb51.net/article/84946.htm demo地址:http://git.oschina.net/lizhanqi/MobSMSDemo 一.前言 ...

  8. 完整的Android手机短信验证源码

    短信验证功能我分两个模块来说,短信验证码的后台和代码实现短信验证码的功能. 一.短信验证码的后台      1.注册Mob账号:http://www.mob.com/#/login 2.注册成功之后, ...

  9. Thinkphp5使用阿里大于短信验证

    现在各种平台登录验证很多时候会使用短信验证,快捷安全,有很多平台提供短信验证服务,相比较而言阿里大于价格比较便宜,快捷,所以在在千锋日常的php教学中多以此为例来说明短信验证的使用.下面我们在tp5中 ...

随机推荐

  1. WCF、Net remoting、Web service概念及区别

    Windows通信基础(Windows Communication Foundation,WCF)是基于Windows平台下开发和部署服务的软件开发包(Software Development Kit ...

  2. 菜鸟教程之工具使用(十)——用BlazeMeter录制JMeter测试脚本

    工具: 1,JMeter 2,Chrome 3,BlazeMeter 4,SwitchyOmega(如果需要代理) 步骤: 以上工具准备好以后就可以录制JMeter的测试脚本了, 在Chrome中点击 ...

  3. Knockout 新版应用开发教程之Observable Arrays

    假如你想到侦测和相应一个对象的改变,假如你想要侦测和响应一一组合集的改变,就要用observableArray 在许多场景都是很有用的,比如你要在UI上需要显示/编辑的一个列表数据集合,然后对集合进行 ...

  4. 20道C&num;练习题(二)11——20题

    11.一个游戏,前20关是每一关自身的分数,1-30关每一关是10分,31-40关,每一关是20分,1-49关,每一关是30分,第50关是100分,输入你现在闯到的关卡数,求你现在拥有的分数.利用if ...

  5. Java操作图片的工具类

    操作图片的工具类: import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.a ...

  6. ORACLE和SQL SERVER的数据同步常用方法

    ORACLE和SQL SERVER的数据同步常用方法 1. 自己编程,或者第三方工具2. 在sqlserver中,使用linkedserver,访问oracle,然后编写job进行数据同步3. 在or ...

  7. 201521123109 《java程序设计》第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  8. 南阳OJ-12-喷水装置(二)贪心&plus;区间覆盖

    题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=12 题目大意: 有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有 ...

  9. &lbrack;转&rsqb;AI&plus;RPA 融合更智能

    本文转自:https://www.jianshu.com/p/cf25b3dfc0f0 前面已经分析过多次RPA的本质,可以参考 [脱下外衣],看看RPA机器人到底是什么?     哪些AI相关应用技 ...

  10. JavaScript字符串操作方法大全,包含ES6方法

    一.charAt() 返回在指定位置的字符. var str="abc" console.log(str.charAt(0))//a 二.charCodeAt() 返回在指定的位置 ...