php实现对短信验证码发送次数的限制实例讲解


Posted in PHP onMarch 04, 2021

场景

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

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

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

方法如下:

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

<!DOCTYPE html>
<html>
<head></head>
<body>
<!-- 隐藏表单uv_r标识,用于对获取验证码的浏览器进行限制,唯一标识存储于浏览器cookie中。在用户进行获取短信验证码操作时将标识传入后台代码(可以通过js传入后台,此处未提供js代码) -->
<input type="hidden" name="uv_r" value="" id="uv_r">
</body>
<script type=”text/javascript”>
/*
使用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+"=([^;]*)(;|$)");
      if(arr=document.cookie.match(reg))
        return unescape(arr[2]);
      else
        return null;
    }
</script>
</html>

后端PHP短信限制次数等的封装类:

Class regMod{
//定义全局变量,用于设置记录文件的路径
Protected $Root = null;
Public function __construct(){
$this -> Root = APP_PATH."/data/msg_logs/";//自己定义的文件存放位置
}
//获取短信验证码操作(Ajax方法为好)
Public function get_authentication_code(){
if ($_POST['uv_r'] && $_POST['tel']) {
$ip=$_SERVER["REMOTE_ADDR"];//ip
  $tel = $_POST['tel'];//电话
  $uv_r = $_POST['uv_r'];//ur_r标识
  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 "发送验证码";//符合发送条件,发送验证码的操作
} else {
Echo “不发送验证码”;
//当不发送验证码时,将数据存入文件,用于方便查询
$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);
  $this->ajax_return(0, "您今日获取短信验证码的次数过多!");//给用户返回信息,ajax_return()为自写方法(未提供)
  }
}
//以下方法为私有方法
//检测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($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();  }
}
 
}

接下来的一步就是你需要在哪里用到短信限制,比如注册,密码找回,修改密码等方法里,直接实例化此封装的类就可以用了。

到此这篇关于php实现对短信验证码发送次数的限制实例讲解的文章就介绍到这了,更多相关php实现对短信验证码发送次数的限制内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
第七节 类的静态成员 [7]
Oct 09 PHP
使用 eAccelerator加速PHP代码的目的
Mar 16 PHP
编写安全 PHP应用程序的七个习惯深入分析
Jun 08 PHP
PHP 使用header函数设置HTTP头的示例解析 表头
Jun 17 PHP
解析在zend Farmework下如何创立一个FORM表单
Jun 28 PHP
PHP 导出Excel示例分享
Aug 18 PHP
destoon实现VIP排名一直在前面排序的方法
Aug 21 PHP
php中adodbzip类实例
Dec 08 PHP
给PHP开发者的编程指南 第一部分降低复杂程度
Jan 18 PHP
PHP静态成员变量
Feb 14 PHP
ThinkPHP模板标签eq if 中区分0,null,false的方法
Mar 24 PHP
在云虚拟主机部署thinkphp5项目的步骤详解
Dec 21 PHP
swoole锁的机制代码实例讲解
Mar 04 #PHP
PHP实现chrome表单请求数据转换为接口使用的json数据
Mar 04 #PHP
windows系统php环境安装swoole具体步骤
Mar 04 #PHP
php中使用array_filter()函数过滤数组实例讲解
Mar 03 #PHP
php array_map()函数实例用法
Mar 03 #PHP
PHP的imageTtfText()函数深入详解
Mar 03 #PHP
PHP实现爬虫爬取图片代码实例
Mar 03 #PHP
You might like
超级实用的7个PHP代码片段分享
2012/01/05 PHP
记录PHP错误日志 display_errors与log_errors的区别
2012/10/09 PHP
php读取目录所有文件信息dir示例
2014/03/18 PHP
typecho插件编写教程(六):调用接口
2015/05/28 PHP
学习php设计模式 php实现合成模式(composite)
2015/12/08 PHP
[原创]php token使用与验证示例【测试可用】
2017/08/30 PHP
js 高效去除数组重复元素示例代码
2013/12/19 Javascript
jQuery中insertAfter()方法用法实例
2015/01/08 Javascript
简介JavaScript中的push()方法的使用
2015/06/09 Javascript
AngularJS控制器controller正确的通信的方法
2016/01/25 Javascript
判断JS对象是否拥有某属性的方法推荐
2016/05/12 Javascript
JS实现输入框提示文字点击时消失效果
2016/07/19 Javascript
浅析如何利用angular结合translate为项目实现国际化
2016/12/08 Javascript
jQuery实现加入收藏夹功能(主流浏览器兼职)
2016/12/24 Javascript
Extjs表单输入框异步校验的插件实现方法
2017/03/20 Javascript
AngularJs实现聊天列表实时刷新功能
2017/06/15 Javascript
js学习总结之DOM2兼容处理this问题的解决方法
2017/07/27 Javascript
Node.JS 循环递归复制文件夹目录及其子文件夹下的所有文件
2017/09/18 Javascript
angularJS自定义directive之带参方法传递详解
2018/10/09 Javascript
关于微信小程序登录的那些事
2019/01/08 Javascript
JavaScript事件冒泡机制原理实例解析
2020/01/14 Javascript
[48:46]完美世界DOTA2联赛PWL S2 SZ vs FTD.C 第二场 11.19
2020/11/19 DOTA
Python中多线程thread与threading的实现方法
2014/08/18 Python
Python中getattr函数和hasattr函数作用详解
2016/06/14 Python
使用实现pandas读取csv文件指定的前几行
2018/04/20 Python
Django ORM 自定义 char 类型字段解析
2019/08/09 Python
Win10下安装并使用tensorflow-gpu1.8.0+python3.6全过程分析(显卡MX250+CUDA9.0+cudnn)
2020/02/17 Python
AmazeUI在模态框中嵌入表单形成模态输入框
2020/08/20 HTML / CSS
会计工作心得体会
2014/01/13 职场文书
汽车装潢店创业计划书范文
2014/02/05 职场文书
21岁生日感言
2014/02/27 职场文书
2014年十一国庆向国旗敬礼寄语
2014/04/11 职场文书
工作分析计划书
2014/04/30 职场文书
师德模范事迹材料
2014/06/03 职场文书
师德自我剖析材料范文
2014/10/06 职场文书
html粘性页脚的具体使用
2022/01/18 HTML / CSS