thinkphp短信验证注册例子

 


前言
注册时经常需要用到短信验证码,本文记录一下思路和具体实现。
短信验证平台使用云片,短信验证码的生成使用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时再添加。

 

时间: 2024-10-30 17:17:52

thinkphp短信验证注册例子的相关文章

Thinkphp实现短信验证注册功能

前言 注册时经常需要用到短信验证码,本文记录一下思路和具体实现. 短信验证平台使用云片,短信验证码的生成使用thinkphp. 思路 1.用户输入手机号,请求获取短信验证码. 2.thinkphp生成短信验证码,存储,同时和其他参数一起发送请求给云片. 3.云片发送短信验证码到指定手机号. 4.用户输入短信验证码. 5.thinkphp根据验证码是否正确.验证码是否过期两个条件判断是否验证通过. 代码实现 验证接口 接口地址:https://sms.yunpian.com/v1/sms/send

验证码-android应用手机短信验证注册功能如何实现?

问题描述 android应用手机短信验证注册功能如何实现? 最近做一个项目,需要做短信验证注册,验证码接口和注册接口都有,如何实现具体功能?有哪里可以找到源码参考? 解决方案 1.生成一个验证码,存入数据库,并发送给指定号码2.用户注册账号,输入验证码,查询数据库,判断验证码是否正确 解决方案二: android 都有注册了 服务器肯定有了 开放一个注册短信的接口不就好了 请求手机注册 获得验证码 用户输入验证码 对比 成功 就成功失败就失败 不是很简单吗? 解决方案三: 楼下说的已经很详细了,

用户手机注册短信验证

问题描述 用户手机注册短信验证 在做用户注册是忘记密码的时候需要手机验证.... 比如在项目中用手机号注册,然后会收到一个验证信息,正确就成功否则失败!有没有哪位大牛做过,求指导一下,如何做....最好可以有个demo和说下用的哪个运营商稳定些!谢谢了

java-Java注册页面的手机短信验证

问题描述 Java注册页面的手机短信验证 如何实现该功能?一定要接口么?谢谢大神指教,最近要实现一个短信验证功能 解决方案 我之前的公司与运营商建立了合作关系,他们给我一个mysql数据库IP地址以及数据库名.数据库的用户名和密码,他们告诉我,只需将短信的内容插入到他们的表中,然后就可以自动发送了.表的结构非常简单,只有二三个字段,其中一个字段是手机号.另一个字段是短信内容.我需要做的就是利用jsp,连接数据库服务器,然后向他们提供的数据库的表中插入记录.就这么简单.我估计他们那边也有一个系统,

短信验证——上行和下行

短信验证码 短信下行 短信下行的使用场景 短信验证码就是最常用的一个短信下行的例子,相对于传统的图片验证码,短信验证码最大的好处就是提升了账号的有效性,注册这一般都是使用自己的手机号吗.当然了,除此之外短信验证码还可以用于登陆,方便快捷. 短信下行的设计 短信下行的验证方式,较上行验证码简单很多,这里以短信验证码为例: 用户输入数据号. 点击获取验证码. 后端收到请求,根据手机号生成验证码,放入缓存,设置有效期,验证码以手机短信的形式发给用户. 用户收到验证码,进行校验. 请求后端进行校验. 服

androidstudio导入项目工程库及短信验证实现(SMSSDK)

一.对应用实现短信验证及手机注册    mob.com . https://www.juhe.cn/juhesdk(聚合数据SDK).BMOB后端云 等官网可看其相关文档学习.   (本人这里是用mob.com官网的类库实现)   1.首先在Mob.com官网注册账号,开通需要的服务创建自己的app, 这样就可以得到相应的appkey和app Secret 这在后面的实现代码中的是需要的.    2.下载相应SDK文件如下: (这是短信验证码对应的SDK,下载完解压)     3.1在实现的代码

Thinkphp5使用阿里大于短信验证

现在各种平台登录验证很多时候会使用短信验证,快捷安全,有很多平台提供短信验证服务,相比较而言阿里大于价格比较便宜,快捷,所以在在千锋日常的PHP教学中多以此为例来说明短信验证的使用.下面我们在tp5中说明如何使用阿里大于进行短信验证. 一.首先到阿里大于平台上注册,创建应用 阿里大于地址为:https://www.alidayu.com/,点击免费入住,然后注册,注册完毕后,进入管理中心.如下图所示在左边导航栏里选择---应用管理,然后在右边内容窗口里选择创建应用.   在左侧导航栏里选择应用管

如何利用 LTE/4G 伪基站+GSM 中间人攻击攻破所有短信验证 ,纯干货!| 硬创公开课

   这次公开课请来的嘉宾对自己的简介是: 连续创业失败的创业导师: 伪天使投资人: 某非知名私立大学创办人兼校长: 业余时间在本校通信安全实验室打杂. 自从他在黑客大会上演讲<伪基站高级利用技术--彻底攻破短信验证码>后,黑产就盯上了这项技术.他们给能仿制这项攻击方法的人开价保底一个月 200 万元,外加分成. 这个攻击方法其实1秒钟可以血洗很多个银行账号.他说,保守估计一小时能带来 7000 万元的黑产产值.但是,他并不是为了钱.他的原话是:"短信验证码这种安全机制朽而不倒,我想

Android实现短信验证功能的代码_Android

在我们现在开发APP过程中,当用户注册时,短信验证是必不可少的操作,这里我们就是用一个免费的第三方短信验证SDK-MOP 首先看下效果图 获取AppKey和AppSecret 首先进入官网,登录(没有帐号的自己去注册一个).鼠标移动到右侧头像处,点击进入后台. 官网首页 选择SecurityCodeSDK. 选择短信SDK 进入后台页面后,点击添加按钮.填写应用名称(这个可以随便写).选择Android后,点击添加即可.   添加应用 添加成功后,就会进入以下界面,在这里就可以看到刚刚申请成功的