比如要实现

单个ip限制60秒1次
单个关键字,比如手机号,限制60秒1次,3600秒10次

<?php
class Sina_Mail_WebAntispam { const PREFIX_WHITELIST = 'w:';
const PREFIX_KILL = 'k:';
const PREFIX_VERIFYCODE = 'c:';
const PREFIX_VERIFIED = 'v:';
const STATUS_UPDATE = '[U]'; private $mc = null;
private $config = null;
private $whitelist = array();
private $keyPrefix = '';
private $intervals = array();
private $updates = array();
private $status = array(); public function __construct($mc, $config) {
$this->mc = $mc;
$this->config = $config;
if (isset($this->config->prefix)) {
$this->keyPrefix = $this->config->prefix;
}
if (isset($this->config->whitelistKey)) {
$wls = $this->mc->get($this->config->whitelistKey);
if (!empty($wls)) {
$this->whitelist = & $wls;
}
}
} public function setWhitelist(&$whitelist) {
$this->whitelist = & $whitelist;
}
/*验证限制规则*/
public function check($ip = null, $key = null) {
if (!$ip && !$key) {
return false;
} if ($key) {
if (!is_array($key)) {
$keys = array($key);
} else {
$keys = $key;
}
} // first filter by whitelist
if (!empty($this->whitelist)) {
if ($ip && $this->filterByWhitelist($ip, 'ip')) {
$this->status[self::PREFIX_WHITELIST . $ip] = 1;
return true;
}
if ($keys) {
foreach ($keys as $key) {
if ($this->filterByWhitelist($key, 'key')) {
$this->status[self::PREFIX_WHITELIST . $key] = 1;
return true;
}
}
}
} if ($ip) {
$ip = $this->keyPrefix . $ip;
} // second, check verified ok
if (!empty($this->config->verified)) {
if ($ip && $this->mc->get(self::PREFIX_VERIFIED . $ip)) {
$this->status[self::PREFIX_VERIFIED . $ip] = 1;
return true;
}
if ($keys) {
foreach ($keys as $key) {
$verifiedKey = self::PREFIX_VERIFIED . $this->keyPrefix . $key;
if ($this->mc->get($verifiedKey)) {
$this->status[$verifiedKey] = 1;
return true;
}
}
}
} $kos = !empty($this->config->kill);
// check killed
if ($kos) {
if ($ip && $this->mc->get(self::PREFIX_KILL . $ip)) {
$this->status[self::PREFIX_KILL . $ip] = 1;
return false;
}
if ($keys) {
foreach ($keys as $key) {
$killKey = self::PREFIX_KILL . $this->keyPrefix . $key;
if ($this->mc->get($killKey)) {
$this->status[$killKey] = 1;
return false;
}
}
}
} // check ip rule
if ($ip && isset($this->config->ip)) {
if (!$this->checkRule($ip, $this->config->ip)) {
if ($kos && $this->mc->set(self::PREFIX_KILL . $ip, 1, intval($this->config->kill))) {
$this->status[self::PREFIX_KILL . $ip] = 1;
}
return false;
}
} // check keys rule
if ($keys && isset($this->config->key)) {
foreach ($keys as $key) {
if (!$this->checkRule($this->keyPrefix . $key, $this->config->key)) {
$killKey = self::PREFIX_KILL . $this->keyPrefix . $key;
if ($kos && $this->mc->set($killKey, 1, intval($this->config->kill))) {
$this->status[$killKey] = 1;
}
return false;
}
}
} return true;
}
/*更新限制规则*/
public function update($c = 1, $ip = null, $key = null) {
if (is_null($ip) && is_null($key)) {
if (!empty($this->updates)) {
foreach ($this->updates as $k => $v) {
if (!$v && isset($this->intervals[$k])) {
if ($this->mc->add($k, $c, false,$this->intervals[$k])) {
$this->status[self::STATUS_UPDATE . $k] = $c;
continue;
}
}
$r = $this->mc->increment($k, $c);
$this->status[self::STATUS_UPDATE . $k] = $r;
}
}
} else {
if (!is_null($ip) && isset($this->config->ip)) {
$rule = $this->config->ip;
foreach ($rule as $interval => $limit) {
$k = $this->keyPrefix . $ip . '_' . $interval;
if ($this->mc->add($k, $c,false,$interval)) {
$this->status[self::STATUS_UPDATE . $k] = true;
continue;
}
$r = $this->mc->increment($k, $c);
$this->status[self::STATUS_UPDATE . $k] = $r;
}
}
if (!is_null($key) && isset($this->config->key)) {
$rule = $this->config->key;
if (!is_array($key)) {
$keys = array($key);
} else {
$keys = $key;
}
foreach ($keys as $key) {
foreach ($rule as $interval => $limit) {
$k = $this->keyPrefix . $key . '_' . $interval;
if ($this->mc->add($k, $c,false,$interval)) {
$this->status[self::STATUS_UPDATE . $k] = true;
continue;
}
$r = $this->mc->increment($k, $c);
$this->status[self::STATUS_UPDATE . $k] = $r;
}
}
}
}
} public function checkVerifyCode($key, $code) {
$servcode = $this->mc->get(self::PREFIX_VERIFYCODE . $this->keyPrefix . $key);
if (strcasecmp($servcode, $code) == 0) {
$verified = intval($this->config->verified);
if ($verified > 0) {
$r = $this->mc->set(self::PREFIX_VERIFIED . $this->keyPrefix . $key, 1, false, $verified);
} else {
$r = true;
}
if ($r) {
$this->mc->delete(self::PREFIX_VERIFYCODE . $this->keyPrefix . $key);
}
return $r;
}
return false;
} public function isVerified($key) {
$r = $this->mc->get(self::PREFIX_VERIFIED . $this->keyPrefix . $key);
if (!empty($r)) {
return true;
} else {
return false;
}
} public function setVerifyCode($key, $code) {
$verifytime = intval($this->config->verifytime);
if ($verifytime < 1) {
return false;
}
return $this->mc->set(self::PREFIX_VERIFYCODE . $this->keyPrefix . $key, $code, false, $verifytime);
} public function getStatus() {
return $this->status;
} private function filterByWhitelist($value, $key) {
// if (empty($this->whitelist[$key])) {
// return false;
// }
// $ls = & $this->whitelist[$key];
$ls = & $this->whitelist;
foreach ($ls as $i) {
if ($i[strlen($i) - 1] == '.') { // ip segment
if (strpos($value, $i) === 0) {
return true;
}
} else {
if (strcmp($i, $value) === 0) {
return true;
}
}
}
return false;
} private function checkRule($key, $rule) {
$flag = true;
if (!empty($rule)) {
foreach ($rule as $interval => $limit) {
$k = $key . '_' . $interval;
$c = $this->mc->get($k);
if (!$c) {
$this->updates[$k] = 0;
$this->intervals[$k] = $interval;
$this->status[$k] = 0;
} else {
$this->updates[$k] = $c;
$this->status[$k] = $c;
if ($c >= $limit) {
$flag = false;
}
}
}
}
return $flag;
} public static function getInstance($conf) {
$mc = new Memcache();
$mc->connect("115.159.28.112");
$conf=json_decode(json_encode($conf));
return new self($mc, $conf);
} }
/*
单个ip限制60秒1次
单个关键字,比如手机号,限制60秒1次,3600秒10次
*/
$conf=array(
'prefix' => 'selfservice:',
'key' => array(60 => 1,3600=>10),
'ip' => array(60 => 1),
);
$spam=Sina_Mail_WebAntispam::getInstance($conf);
if(!$spam->check('127.25.12.123',17610725730)){
echo "limit...";
exit;
} //更新频率限制
$spam->update();

  

memache中最终的存储key

[PHP] 频率限制类的更多相关文章

  1. 频率类组件-认证规图分析-JWT认证-drf-jwt插件

    频率类源码 # 1)APIView的dispath方法中的 self.initial(request, *args, **kwargs) 点进去 # 2)self.check_throttles(re ...

  2. web系统访问频率限制

    无论是spring mvc还是struts,都可以为controller或者aciton执行前,增加拦截器. 通过拦截器中的逻辑控制,可以实现访问频率的限制. 首先构造访问频率数据类 class Fr ...

  3. DRF之频率限制、分页、解析器和渲染器

    一.频率限制 1.频率限制是做什么的 开放平台的API接口调用需要限制其频率,以节约服务器资源和避免恶意的频繁调用. 2.频率组件原理 DRF中的频率控制基本原理是基于访问次数和时间的,当然我们可以通 ...

  4. DRF 权限和频率

    Django Rest Framework 权限组件 DRF的权限 权限组件源码解析 我们之前说过了DRF的版本和认证~也知道了权限和频率跟版本认证都是在initial方法里初始化的~~ 其实我们版本 ...

  5. DRF 权限 频率

    DRF的权限 权限是什么 大家之前都应该听过权限~那么我们权限到底是做什么用的呢~~ 大家都有博客~或者去一些论坛~一定知道管理员这个角色~ 比如我们申请博客的时候~一定要向管理员申请~也就是说管理员 ...

  6. Django的rest_framework的权限组件和频率组件源码分析

    前言: Django的rest_framework一共有三大组件,分别为认证组件:perform_authentication,权限组件:check_permissions,频率组件:check_th ...

  7. drf6 权限和频率控制组件

    对某件事情决策的范围和程度,我们叫做权限,权限是我们在项目开发中非常常用到的. DRF框架给我们提供的权限组件 权限组件 之前DRF的版本和认证,知道了权限和频率跟版本认证都是在initial方法里初 ...

  8. Restful framework【第八篇】频率组件

    基本使用 频率: -限制每个ip地址一分钟访问10次 -写一个类 from rest_framework.throttling import SimpleRateThrottle class Visi ...

  9. DRF的权限和频率

    DRF的权限 权限组件源码 权限和频率以及版本认证都是在initial方法里初始化的 我们的权限类一定要有has_permission方法~否则就会抛出异常~~这也是框架给我提供的钩子~~ 在rest ...

随机推荐

  1. 微信小程序开发---各代码文件简介

    根据上一文,已建立QuickStart 项目,该项目系本人毕设部分内容,所以记录以便以后查阅 开发小程序就必须了解小程序项目目录结构和文件作用,接下来就根据我现在自学得到的知识把这些记录下来. 一.目 ...

  2. ECharts使用:this.dom.getContext is not a function

    echarts 画图报错 this.dom.getContext is not a function; 原因:因为在初始化echarts的时候,echarts.js规定只能使用dom原生方法获取标签, ...

  3. 查看 FormData 中已存在的值

    var formData = new FormData(); formData.append('name','bob'); formData.append('sex','male'); formDat ...

  4. NodeJS NPM 镜像使用方法

    每次npm的时候,走国外的镜像,非常的慢,可以配置一下 通过改变默认npm镜像代理服务,以下三种办法任意一种都能解决问题,建议使用第三种,将配置写死,下次用的时候不用重新配置. 通过config命令 ...

  5. EF Oracle:错误 175

    错误 1 错误 175: 具有固定名称“Oracle.DataAccess.Client”的 ADO.NET 提供程序未在计算机或应用程序配置文件中注册或无法加载.有关详细信息,请参阅内部异常. 安装 ...

  6. [Swift]LeetCode675. 为高尔夫比赛砍树 | Cut Off Trees for Golf Event

    You are asked to cut off trees in a forest for a golf event. The forest is represented as a non-nega ...

  7. [Swift]LeetCode832. 翻转图像 | Flipping an Image

    Given a binary matrix A, we want to flip the image horizontally, then invert it, and return the resu ...

  8. Hystrix概念设计

    1. Hystrix概念设计 1.1. 大纲 1.2. 基本的容错模式 1.3. 断路器模式 1.4. 舱壁隔离模式 1.5. 容错理念 凡事依赖都可能失败 凡事资源都有限制 网络并不可靠 延迟是应用 ...

  9. SSM框架报HTTP Status 500 - Request processing failed; nested exception is java.lang.NullPointerException错

    如下图 一番排查之后发现原来是server层写漏注释了 粗心大意,一天内出现两次写漏注释,SSM框架有意思.

  10. python之Django学习笔记(三)---URL调度/URL路由

    在django中,用户发起url请求消息首先到工程的urls.py中查找是否有匹配的url路径 刚创建好的工程中urls.py只有下面几行代码: from django.contrib import ...