龙行博客

走路看风景,经历看人生,岁月留痕迹,人生留轨迹,17的历史,18的豪情,时间的匆忙,人生的风景,放开心胸往前走,成功再远行,放开理想往前走,梦想再行动。
现在位置:首页 > 编程语言 > PHP > 对短信验证码发送次数的限制,用PHP是如何实现

对短信验证码发送次数的限制,用PHP是如何实现

龙行    PHP    2019-6-13    2914    0评论    

场景


在注册,修改密码,找回密码等场景里,我们都会遇到发送手机短信进行验证码验证,我们都知道,手机的这个短信接口是需要购买了,为了防刷,我们就会对短信验证码发送次数的限制,我们应该如何防止呢?


很多人都会这样做:对用户获取短信验证码的手机号、ip、和浏览器(使用唯一标识)进行限制。


本文介绍的方法是对用户每天只能通过同一浏览器或同一ip地址获取验证码10次或者同一手机号只能获取3次短信验证码,三种限制为“或”关系,一条超限就不发验证码。方法是通过在服务器端将用户的手机号、ip、ur_r标识记录并写入文件,再通过读取文件记录判断用户请求发送验证码的次数来做限制。


方法如下:


这里是获取短信验证码页面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>

<!-- 隐藏表单uv_r标识,用于对获取验证码的浏览器进行限制,唯一标识存储于浏览器cookie中。在用户进行获取短信验证码操作时将标识传入后台代码(可以通过js传入后台,此处未提供js代码) -->
<form action="./chuli.php" method="post">
<input type="hidden" name="uv_r" value="" id="uv_r">
<input type="text" name="tel" value="" >  电话
<input type="submit" value="提交">
</form>
</body>
<script>
    /**
     使用js获取cookie中ur_r唯一标识,如果不存在,生成唯一标识,js写入cookie,并将唯一标识赋给隐藏表单。
     */
        //唯一标识存入cookie
    var _uuid = getUUID();
    if (getCookie("_UUID_UV") != null && getCookie("_UUID_UV") != undefined) {
        _uuid = getCookie("_UUID_UV");
    } else {
        setCookie("_UUID_UV", _uuid);
    }

    document.getElementById("uv_r").value = _uuid;//赋给hidden表单

    //生成唯一标识

    function getUUID() {
        var uuid = new Date().getTime();
        var randomNum = parseInt(Math.random() * 1000);
        return uuid + randomNum.toString();
    }

    //写cookie

    function setCookie(name, value) {
        var Days = 365;//这里设置cookie存在时间为一年
        var exp = new Date();
        exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
        document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();

    }

    //获取cookie
    function getCookie(name) {
        var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
        console.log(document.cookie.match(reg));
        if (arr = document.cookie.match(reg))
            return unescape(arr[2]);
        else
            return null;
    }
    console.log(_uuid);
</script>

</html>
后端PHP短信限制次数等的封装类(这个类还有点问题看你是怎么调用了 稍作修改,太懒,不想弄)
<?php

Class regMod
{

//定义全局变量,用于设置记录文件的路径

    Protected $Root = null;
    Public function __construct()
    {
        $this->Root =  "./";//自己定义的文件存放位置
    }

//获取短信验证码操作(Ajax方法为好)

    Public function get_authentication_code($ip = '',$tel = '', $uv_r = '')
    {
        if ($uv_r && $tel) {
            if (empty($uv_r)) {
                $uv_r = 0;
            }
        }

        //判断数据是否超过了限制
        $uvr_num = $this->checkUvr($uv_r);
        $tel_num = $this->checkTel($tel);
        $ip_num = $this->checkIp($ip);
        if ($uvr_num < 10 && $tel_num < 4 && $ip_num < 10) {
            echo "发送验证码";//符合发送条件,发送验证码的操作
            return 1; //验证码发送成功,返回1
        } else {

//当不发送验证码时,将数据存入文件,用于方便查询
            $data = $tel . "|" . $ip . "|" . $uv_r . "|";
            if ($uv_r > 0 && $uvr_num >= 10) {
                $data = $data . "A@";
            }
            if ($tel_num >= 4) {
                $data = $data . "B@";
            }
            if ($ip_num >= 10) {
                $data = $data . "C@";
            }
            $this->wirteFile("", $data);
            return 2; //发送次数过多
        }

    }

//以下方法为私有方法

//检测ur_r在文件中出现的次数

    Private function checkUvr($data)
    {
        $fileName = "Uv_" . date("Ymd", time()) . ".dat";
        $filePath = ($this->Root) . $fileName;//组装要写入的文件的路径
        $c_sum = 0;
        if (file_exists($filePath)) {//文件存在获取次数并将此次请求的数据写入
            $arr = file_get_contents($filePath);
            $row = explode("|", $arr);
            $countArr = array_count_values($row);
            $c_sum = $countArr[$data];
            if ($c_sum < 10) {
                $this->wirteFile($filePath, $data . "|");
            }
            return $c_sum;
        } else {//文件不存在创建文件并写入本次数据,返回次数0
            $this->wirteFile($filePath, $data . "|");
            return $c_sum;
        }

    }

//检测Tel在文件中出现的次数

    Private function checkTel(string $data)
    {
        $fileName = "Tel_" . date("Ymd", time()) . ".dat";
        $filePath = ($this->Root) . $fileName;
        $c_sum = 0;
        if (file_exists($filePath)) {
            $arr = file_get_contents($filePath);
            $row = explode("|", $arr);
            $countArr = array_count_values($row);
            $c_sum = $countArr[$data];
            if ($c_sum < 4) {
                $this->wirteFile($filePath, $data . "|");
            }
            return $c_sum;
        } else {
            $this->wirteFile($filePath, $data . "|");
            return $c_sum;
        }
    }

//检测IP在文件中存在的次数

    Private function checkIp($data)
    {
        $fileName = "Ip_" . date("Ymd", time()) . ".dat";
        $filePath = ($this->Root) . $fileName;
        $c_sum = 0;
        if (file_exists($filePath)) {
            $arr = file_get_contents($filePath);
            $row = explode("|", $arr);
            $countArr = array_count_values($row);
            $c_sum = $countArr[$data];
            if ($c_sum < 10) {
                $this->wirteFile($filePath, $data . "|");
            }
            return $c_sum;
        } else {
            $this->wirteFile($filePath, $data . "|");
            return $c_sum;
        }
    }

    /**
     * 将数据写入本地文件
     * @param $filePath 要写入文件的路径
     * @param $data 写入的数据
     */

    Private function wirteFile($filePath, $data)
    {
        try {
            if (!is_dir($this->Root)) {//判断文件所在目录是否存在,不存在就创建
                mkdir($this->Root, 0777, true);
            }
            if ($filePath == "") {//此处是不发送验证码时,记录日志创建的文件
                $filePath = ($this->Root) . "N" . date("Ymd", time()) . ".dat";
            }

//写入文件操作
            $fp = fopen($filePath, "a+");//得到指针
            fwrite($fp, $data);//写
            fclose($fp);//关闭
        } catch (Exception $e) {
            print $e->getMessage();
        }
    }
}

?>
调用方法(上面说了看你怎么调用 你用ajax可以改下,类里面的方法都是测试过实现没问题)

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/6/13 0013
 * Time: 10:23
 */

include_once  './index.php';
$y = new regMod();
$tel = 13980718991;
$uv_r = $_POST['uv_r'];
$ip = '117.45.123.58';
$a = $y->get_authentication_code($ip, $tel ,$uv_r);
var_dump($a);

评论一下 分享本文 赞助站长

赞助站长X

扫码赞助站长
联系站长
龙行博客
  • 版权申明:此文如未标注转载均为本站原创,自由转载请表明出处《龙行博客》。
  • 本文网址:https://www.liaotaoo.cn/249.html
  • 上篇文章:jquery实现左侧伸缩菜单
  • 下篇文章:php-curl各种请求
  • php
快捷导航
联系博主
在线壁纸
给我留言
四四五五
音乐欣赏
返回顶部