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 相关文章推荐
用PHP制作静态网站的模板框架
Oct 09 PHP
php self,$this,const,static,-&amp;gt;的使用
Oct 22 PHP
PHP的autoload机制的实现解析
Sep 15 PHP
无需重新编译php加入ftp扩展的解决方法
Feb 07 PHP
解析php利用正则表达式解决采集内容排版的问题
Jun 20 PHP
php自动识别文字编码并转换为目标编码的方法
Aug 08 PHP
php实现购物车功能(下)
Jan 05 PHP
基于PHP实现等比压缩图片大小
Mar 04 PHP
php遍历、读取文件夹中图片并分页显示图片的方法
Nov 15 PHP
php安全配置记录和常见错误梳理(总结)
Mar 28 PHP
PHP操作Redis数据库常用方法示例
Aug 25 PHP
PHP使用SMTP邮件服务器发送邮件示例
Aug 28 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
《Re:从零开始的异世界生活 冰结之绊》
2020/04/09 日漫
杏林同学录(二)
2006/10/09 PHP
php中通过curl模拟登陆discuz论坛的实现代码
2012/02/16 PHP
PHP设计模式之状态模式定义与用法详解
2018/04/02 PHP
PHP获取数据库表中的数据插入新的表再原删除数据方法
2018/10/12 PHP
Laravel使用scout集成elasticsearch做全文搜索的实现方法
2018/11/30 PHP
JQuery困惑—包装集 DOM节点
2009/10/16 Javascript
比Jquery的document.ready更快的方法
2010/04/28 Javascript
js之onload事件的一点使用心得
2013/08/14 Javascript
jquery.cookie() 方法的使用(读取、写入、删除)
2013/12/05 Javascript
使用node.js半年来总结的 10 条经验
2014/08/18 Javascript
基于NodeJS的前后端分离的思考与实践(五)多终端适配
2014/09/26 NodeJs
JavaScript实现为指定对象添加多个事件处理程序的方法
2015/04/17 Javascript
JavaScript简单实现弹出拖拽窗口(一)
2016/06/17 Javascript
最简单纯JavaScript实现Tab标签页切换的方式(推荐)
2016/07/25 Javascript
浅谈JavaScript中变量和函数声明的提升
2016/08/09 Javascript
郁闷!ionic中获取ng-model绑定的值为undefined如何解决
2016/08/27 Javascript
浅谈JS中的三种字符串连接方式及其性能比较
2016/09/02 Javascript
详解vue-router 2.0 常用基础知识点之导航钩子
2017/05/10 Javascript
浅析Vue中method与computed的区别
2018/03/06 Javascript
JavaScript分步实现一个出生日期的正则表达式
2018/03/22 Javascript
jQuery实现动态添加和删除input框实例代码
2019/03/26 jQuery
深入了解JavaScript 的 WebAssembly
2019/06/15 Javascript
从0搭建vue-cli4脚手架
2020/06/17 Javascript
python创建只读属性对象的方法(ReadOnlyObject)
2013/02/10 Python
学习python 之编写简单乘法运算题
2016/02/27 Python
Python中函数eval和ast.literal_eval的区别详解
2017/08/10 Python
PyTorch 解决Dataset和Dataloader遇到的问题
2020/01/08 Python
python绘制汉诺塔
2021/03/01 Python
班组长安全生产职责
2013/12/16 职场文书
迎新晚会策划方案
2014/06/13 职场文书
大学迎新生标语
2014/10/06 职场文书
2014年林业工作总结
2014/12/05 职场文书
2015年司法局工作总结
2015/05/22 职场文书
公务员爱岗敬业心得体会
2016/01/25 职场文书
React如何使用axios请求数据并把数据渲染到组件
2022/08/05 Javascript