接口做下安全处理,封装类(待补充)
<?php
/**
* Created by PhpStorm.
* User: walkingsun
* Date: 2018/2/5
* Time: 下午9:45
*/
class apiFiter{
private $redisObj; //redis操作对象
private $uniqeUser; //唯一用户标识
private $requestData; //请求参数
private $isAjax; //是否ajax
private $isPost; //是否post
private $isReSubmit; //是否重复
private $isVilentSubmit; //暴力提交
private $maxRequest; //每分钟最大提交次数
private $headData; //获取头信息
public function __construct( $uniqeUser,$redisObj,$isAjax='',$isPost='',$isReSubmit='',$isVilentSubmit='',$maxRequest='' )
{
$this->redisObj = $redisObj;
$this->isAjax = $isAjax;
$this->isPost = $isPost;
$this->isReSubmit = $isReSubmit;
$this->isVilentSubmit = $isVilentSubmit;
$this->maxRequest = $maxRequest?:5000;
$this->uniqeUser = $uniqeUser;
$this->requestData = $_SERVER['REQUEST_URI'].'_'.md5(file_get_contents("php://input"));
$this->headData = $_SERVER;
$this->run();
}
public function run(){
if( $this->isAjax ) $this->isAjax();
if( $this->isPost ) $this->isPost();
if( $this->isReSubmit ) $this->isReSubmit();
if( $this->isVilentSubmit ) $this->isVilentSubmit();
}
/**
* 判断是否为ajax方式
*/
private function isAjax(){
if( !( isset($this->headData["HTTP_X_REQUESTED_WITH"]) && strtolower($this->headData["HTTP_X_REQUESTED_WITH"])=="xmlhttprequest" ) ){
throw new Exception('请求不合法',400);
}
return true;
}
/**
* 判断是否为post方式
*/
private function isPost(){
if( $this->headData['REQUEST_METHOD'] != 'POST' ){
throw new Exception('请求不合法',400);
}
return true;
}
/**
* 判断是否重复提交
*/
private function isReSubmit(){
$key = ($this->uniqeUser.'_'.$this->requestData);
if( $this->redisObj->exists($key) ){
throw new Exception('重复提交',401);
}
$this->redisObj->setex($key,60,'1');
return true;
}
/**
* 是否暴力提交
*/
private function isVilentSubmit(){
$time = date('YmdHi');
$key = $this->uniqeUser.'_vilent'; //暴力检测key
//存在锁定标识,返回锁定异常
if( $this->redisObj->exist($key.'_forbidden') ){
$limit_time = $this->redisObj->ttl($key.'_forbidden');
throw new Exception("您的请求锁定2小时,剩余时间{$limit_time}秒",500);
}
//创建暴力标识
if( !$this->redisObj->exists($key.$time) ){
$this->redisObj->setex($key,60,0);
}
//获取当前暴力标识 值
$num = $this->redisObj->get($key.$time);
//如果分钟内的暴力标识值超过最大限制,锁定用户
if( $num >= $this->maxRequest ){
$this->redisObj->setex( $key.'_forbidden',7200,'' );
throw new Exception('请求过于频繁,锁定2小时',500);
}
//递增标识值
$this->redisObj->incr($key.$time);
}
}
/* 调用实例 拦截暴力提交 */
$uniqeUser = 'userid123';
$redisObj = \Yii::$app->redis;
try{
$apifiter = new apiFiter($uniqeUser,$redisObj,$isAjax='',$isPost='',$isReSubmit='',$isVilentSubmit=1,$maxRequest='500');
$apifiter->run();
}catch (Exception $e){
$errorData = ['code'=>$e->getCode(),'msg'=>$e->getMessage()];
echo json_encode($errorData);
}