场景


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


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


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


方法如下:


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

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. </head>
  6. <body>
  7.  
  8. <!-- 隐藏表单uv_r标识,用于对获取验证码的浏览器进行限制,唯一标识存储于浏览器cookie中。在用户进行获取短信验证码操作时将标识传入后台代码(可以通过js传入后台,此处未提供js代码) -->
  9. <form action="./chuli.php" method="post">
  10. <input type="hidden" name="uv_r" value="" id="uv_r">
  11. <input type="text" name="tel" value="" > 电话
  12. <input type="submit" value="提交">
  13. </form>
  14. </body>
  15. <script>
  16. /**
  17. 使用js获取cookie中ur_r唯一标识,如果不存在,生成唯一标识,js写入cookie,并将唯一标识赋给隐藏表单。
  18. */
  19. //唯一标识存入cookie
  20. var _uuid = getUUID();
  21. if (getCookie("_UUID_UV") != null && getCookie("_UUID_UV") != undefined) {
  22. _uuid = getCookie("_UUID_UV");
  23. } else {
  24. setCookie("_UUID_UV", _uuid);
  25. }
  26.  
  27. document.getElementById("uv_r").value = _uuid;//赋给hidden表单
  28.  
  29. //生成唯一标识
  30.  
  31. function getUUID() {
  32. var uuid = new Date().getTime();
  33. var randomNum = parseInt(Math.random() * 1000);
  34. return uuid + randomNum.toString();
  35. }
  36.  
  37. //写cookie
  38.  
  39. function setCookie(name, value) {
  40. var Days = 365;//这里设置cookie存在时间为一年
  41. var exp = new Date();
  42. exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
  43. document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
  44.  
  45. }
  46.  
  47. //获取cookie
  48. function getCookie(name) {
  49. var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
  50. console.log(document.cookie.match(reg));
  51. if (arr = document.cookie.match(reg))
  52. return unescape(arr[2]);
  53. else
  54. return null;
  55. }
  56. console.log(_uuid);
  57. </script>
  58.  
  59. </html>
后端PHP短信限制次数等的封装类(这个类还有点问题看你是怎么调用了 稍作修改,太懒,不想弄)
  1. <?php
  2.  
  3. Class regMod
  4. {
  5.  
  6. //定义全局变量,用于设置记录文件的路径
  7.  
  8. Protected $Root = null;
  9. Public function __construct()
  10. {
  11. $this->Root = "./";//自己定义的文件存放位置
  12. }
  13.  
  14. //获取短信验证码操作(Ajax方法为好)
  15.  
  16. Public function get_authentication_code($ip = '',$tel = '', $uv_r = '')
  17. {
  18. if ($uv_r && $tel) {
  19. if (empty($uv_r)) {
  20. $uv_r = 0;
  21. }
  22. }
  23.  
  24. //判断数据是否超过了限制
  25. $uvr_num = $this->checkUvr($uv_r);
  26. $tel_num = $this->checkTel($tel);
  27. $ip_num = $this->checkIp($ip);
  28. if ($uvr_num < 10 && $tel_num < 4 && $ip_num < 10) {
  29. echo "发送验证码";//符合发送条件,发送验证码的操作
  30. return 1; //验证码发送成功,返回1
  31. } else {
  32.  
  33. //当不发送验证码时,将数据存入文件,用于方便查询
  34. $data = $tel . "|" . $ip . "|" . $uv_r . "|";
  35. if ($uv_r > 0 && $uvr_num >= 10) {
  36. $data = $data . "A@";
  37. }
  38. if ($tel_num >= 4) {
  39. $data = $data . "B@";
  40. }
  41. if ($ip_num >= 10) {
  42. $data = $data . "C@";
  43. }
  44. $this->wirteFile("", $data);
  45. return 2; //发送次数过多
  46. }
  47.  
  48. }
  49.  
  50. //以下方法为私有方法
  51.  
  52. //检测ur_r在文件中出现的次数
  53.  
  54. Private function checkUvr($data)
  55. {
  56. $fileName = "Uv_" . date("Ymd", time()) . ".dat";
  57. $filePath = ($this->Root) . $fileName;//组装要写入的文件的路径
  58. $c_sum = 0;
  59. if (file_exists($filePath)) {//文件存在获取次数并将此次请求的数据写入
  60. $arr = file_get_contents($filePath);
  61. $row = explode("|", $arr);
  62. $countArr = array_count_values($row);
  63. $c_sum = $countArr[$data];
  64. if ($c_sum < 10) {
  65. $this->wirteFile($filePath, $data . "|");
  66. }
  67. return $c_sum;
  68. } else {//文件不存在创建文件并写入本次数据,返回次数0
  69. $this->wirteFile($filePath, $data . "|");
  70. return $c_sum;
  71. }
  72.  
  73. }
  74.  
  75. //检测Tel在文件中出现的次数
  76.  
  77. Private function checkTel(string $data)
  78. {
  79. $fileName = "Tel_" . date("Ymd", time()) . ".dat";
  80. $filePath = ($this->Root) . $fileName;
  81. $c_sum = 0;
  82. if (file_exists($filePath)) {
  83. $arr = file_get_contents($filePath);
  84. $row = explode("|", $arr);
  85. $countArr = array_count_values($row);
  86. $c_sum = $countArr[$data];
  87. if ($c_sum < 4) {
  88. $this->wirteFile($filePath, $data . "|");
  89. }
  90. return $c_sum;
  91. } else {
  92. $this->wirteFile($filePath, $data . "|");
  93. return $c_sum;
  94. }
  95. }
  96.  
  97. //检测IP在文件中存在的次数
  98.  
  99. Private function checkIp($data)
  100. {
  101. $fileName = "Ip_" . date("Ymd", time()) . ".dat";
  102. $filePath = ($this->Root) . $fileName;
  103. $c_sum = 0;
  104. if (file_exists($filePath)) {
  105. $arr = file_get_contents($filePath);
  106. $row = explode("|", $arr);
  107. $countArr = array_count_values($row);
  108. $c_sum = $countArr[$data];
  109. if ($c_sum < 10) {
  110. $this->wirteFile($filePath, $data . "|");
  111. }
  112. return $c_sum;
  113. } else {
  114. $this->wirteFile($filePath, $data . "|");
  115. return $c_sum;
  116. }
  117. }
  118.  
  119. /**
  120. * 将数据写入本地文件
  121. * @param $filePath 要写入文件的路径
  122. * @param $data 写入的数据
  123. */
  124.  
  125. Private function wirteFile($filePath, $data)
  126. {
  127. try {
  128. if (!is_dir($this->Root)) {//判断文件所在目录是否存在,不存在就创建
  129. mkdir($this->Root, 0777, true);
  130. }
  131. if ($filePath == "") {//此处是不发送验证码时,记录日志创建的文件
  132. $filePath = ($this->Root) . "N" . date("Ymd", time()) . ".dat";
  133. }
  134.  
  135. //写入文件操作
  136. $fp = fopen($filePath, "a+");//得到指针
  137. fwrite($fp, $data);//写
  138. fclose($fp);//关闭
  139. } catch (Exception $e) {
  140. print $e->getMessage();
  141. }
  142. }
  143. }
  144.  
  145. ?>

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

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Administrator
  5. * Date: 2019/6/13 0013
  6. * Time: 10:23
  7. */
  8.  
  9. include_once './index.php';
  10. $y = new regMod();
  11. $tel = 13980718991;
  12. $uv_r = $_POST['uv_r'];
  13. $ip = '117.45.123.58';
  14. $a = $y->get_authentication_code($ip, $tel ,$uv_r);
  15. var_dump($a);

相关评论(0)
您是不是忘了说点什么?

友情提示:垃圾评论一律封号...

还没有评论,快来抢沙发吧!