多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
http://www.thinkphp.cn/topic/66124.html 整理一下,前端向接口请求数据时的验证:比如我写了一个文章列表数据接口,那么我需要验证哪些规则,由此,我想了一下,**除开签名验证,大概就只有ssl协议,白名单\[ip,域名,url\],黑名单\[ip,域名,url\],请求频率\[eg:每10秒,最大请求数\],设备【电脑,手机】,终端浏览器\[微信,qq,...\],设置请求方式并禁用curl获取数据\[保证用户只能在页面使用ajax请求\]**。 如果不做请求方式的限制,那么就其他人就能通过curl方式获取到数据,于是写了下面一个例子,暂时还没有加入签名验证,后续有时间将把签名加进去。今天先整理这些:` 1. <?php 2. /** 3.  *  +---------------------------------------------------------------------- 4.  *  | ThinkPHP [ WE CAN DO IT JUST THINK ] 5.  *  +---------------------------------------------------------------------- 6.  *  | Copyright (c) 2019 ahai574 All rights reserved. 7.  *  +---------------------------------------------------------------------- 8.  *  | Licensed ( ++++ahai574++++ ) 9.  *  +---------------------------------------------------------------------- 10.  *  | Author: 阿海 <764882431@qq.com> 11.  *  +---------------------------------------------------------------------- 12.  */ 13. /** 14.  * 请求验证 15.  * demo: 16.  * $checkRequest = new CheckRequest(); 17.  *      $checkRequest->setAjax('get',true); 18.  *      $checkRequest->setBlackList('10.0.0.155',false); 19.  *      $checkRequest->setWhiteList('10.0.0.15'); 20.  *      $checkRequest->setDevice('mobile,pc',false); 21.  *      $checkRequest->setTerminal('uc,weixin',false); 22.  *      $checkRequest->setFrequent(10,3,true); 23.  *      $checkRequest->setSsl(false); 24.  *      $result = $checkRequest->check(); 25.  * if(!$result['result']) return json($result); 26.  */ 28. namespace app\common\library; 30. use think\Controller; 31. use think\Exception; 32. use think\facade\Request; 34. classCheckRequestextendsController 35. { 36. /** 37.      * 开启 协议请求 必须是 https 38.      * boolean 39.      */ 40. private $isSsl =false; 42. /** 43.      * 开启 验证请求 为 【页面内】ajax请求 44.      * boolean 45.      */ 46. private $isAjax =true; 48. /** 49.      * ajax请求方式[eg:[post,get,put]] 50.      * array 51.      */ 52. private $ajax =[]; 54. /** 55.      * 是否开启 频繁请求验证 56.      * boolean 57.      */ 58. private $isFrequently =false; 60. /** 61.      * 频繁请求 的 秒数 62.      * int 63.      */ 64. private $requestTime =10; 66. /** 67.      * 频繁请求 ($requestTime)10秒 内 的 最大访问次数 68.      * int 69.      */ 70. private $frequency =50; 72. /** 73.      * 是否开启白名单验证 74.      * boolean 75.      */ 76. private $isWhiteList =false; 78. /** 79.      * ip白名单 或者 域名白名单 80.      * [ 81.      * 完整的域名(eg:http:test.baidu.com),主域名(eg:baidu.com), 82.      * 子域名[eg:test.baidu.com],url完整路径(eg:http://test.baidu.com/test/test.html) 83.      * ] 84.      * array 85.      */ 86. private $whiteList =['127.0.0.1']; 88. /** 89.      * 是否开启黑名单验证  【优先级大于白名单】 90.      * boolean 91.      */ 92. private $isBlackList =false; 94. /** 95.      * ip黑名单 或者 域名黑名单 96.      * [ 97.      * 完整的域名(eg:http:test.baidu.com),主域名(eg:baidu.com), 98.      * 子域名[eg:test.baidu.com],url完整路径(eg:http://test.baidu.com/test/test.html) 99.      * ] 100.      * array 101.      */ 102. private $blackList =[]; 104. /** 105.      * 是否开启设备验证 106.      * boolean 107.      */ 108. private $isDevice =false; 110. /** 111.      * 设备类型 手机[mobile] 电脑['pc']  112.      * array 113.      */ 114. private $device =['mobile']; 116. /** 117.      * 是否开启终端验证 118.      * boolean 119.      */ 120. private $isTerminal =false; 122. /** 123.      * 终端浏览器类型 (eg:['weixin','qq','baidu','uc']) 124.      * array 125.      */ 126. private $terminal =['weixin']; 128. /** 129.      * 构造函数 constructor. 130.      */ 131. publicfunction __construct($config =[]) 132. { 133.         parent::__construct(); 135. if(isset($config)&&!is_array($config)){ 136. thrownewException("构造参数config必须是数组"); 137. } 139.         $this->isSsl = isset($config['isSsl'])&&!empty($config['isSsl'])? $config['isSsl']: $this->isSsl; 141.         $this->isAjax = isset($config['isAjax'])&&!empty($config['isAjax'])? $config['isAjax']: $this->isAjax; 142.         $this->ajax = isset($config['ajax'])&& is_array($config['ajax'])? $config['ajax']: $this->ajax; 144.         $this->isFrequently = isset($config['isFrequently'])&&!empty($config['isFrequently'])? $config['isFrequently']: $this->isFrequently; 145.         $this->requestTime = isset($config['requestTime'])&&!empty($config['requestTime'])? $config['requestTime']: $this->requestTime; 146.         $this->frequency = isset($config['frequency'])&&!empty($config['frequency'])? $config['frequency']: $this->frequency; 148.         $this->isWhiteList = isset($config['isWhiteList'])&&!empty($config['isWhiteList'])? $config['isWhiteList']: $this->isWhiteList; 149.         $this->whiteList = isset($config['whiteList'])&& is_array($config['whiteList'])? array_merge($this->whiteList, $config['whiteList']): $this->whiteList; 151.         $this->isBlackList = isset($config['isBlackList'])&&!empty($config['isBlackList'])? $config['isBlackList']: $this->isBlackList; 152.         $this->blackList = isset($config['blackList'])&& is_array($config['blackList'])? array_merge($this->blackList, $config['blackList']): $this->blackList; 154.         $this->isDevice = isset($config['isDevice'])&&!empty($config['isDevice'])? $config['isDevice']: $this->isDevice; 155.         $this->device = isset($config['device'])&& is_array($config['device'])? $config['device']: $this->device; 157.         $this->isTerminal = isset($config['isTerminal'])&& is_array($config['isTerminal'])? $config['isTerminal']: $this->isTerminal; 158.         $this->terminal = isset($config['terminal'])&& is_array($config['terminal'])? $config['terminal']: $this->terminal; 160. } 162. /** 163.      * 检测请求行为 164.      * @return boolean 165.      */ 166. publicfunction check() 167. { 168. //验证黑名单-- 169. if($this->isBlackList){ 170. //ip,主域名,包含协议域名,请求的url完整路径, 主域名 171.             $requestList =[Request::ip(),Request::host(),Request::domain(),Request::url(true),Request::rootDomain()]; 173. if(!empty(array_intersect($this->blackList, $requestList))){ 174. return['result'=>false,'errorMsg'=>'域名[ip]已被禁用','code'=>200]; 175. }else{ 176. //读取数据库黑名单表 177.                 $list = db('request_blacklist') 178. ->whereOr('ip','eq',Request::ip()) 179. ->whereOr('domain','eq',Request::domain()) 180. ->whereOr('domain','eq',Request::host()) 181. ->whereOr('domain','eq',Request::rootDomain()) 182. ->whereOr('domain','eq',Request::url(true)) 183. ->find(); 184. if(!is_null($list)){ 185. return['result'=>false,'errorMsg'=>'域名[ip]已被禁用','code'=>200]; 186. } 187. } 190. } 192. //验证ssl协议 193. if($this->isSsl){ 194. if(!Request::isSsl()){ 195. return['result'=>false,'errorMsg'=>'请求协议必须是https协议','code'=>200]; 196. } 197. } 199. //验证是否ajax 必须是页面内的请求  [避开curl请求,浏览器直接输入地址] 200. if($this->isAjax){ 201. if(empty($this->ajax)){ 202. if(!Request::isAjax()){ 203. return['result'=>false,'errorMsg'=>'非法请求','code'=>200]; 204. } 205. }else{ 206. if(!in_array(Request::method(), $this->ajax)) 207. { 208. return['result'=>false,'errorMsg'=>'非法请求','code'=>200]; 209. } 210. } 211. } 213. //验证请求频率 214. if($this->isFrequently){ 215.             $data =[ 216. 'method'=>Request::method(), 217. 'param'=>  json_encode(Request::param()), 218. 'ip'=>Request::ip(), 219. 'url'=>Request::url(true), 220. 'http_user_agent'=>  $_SERVER['HTTP_USER_AGENT'], 221. 'is_mobile'=>Request::isMobile()?1:0, 222. 'create_time'=>  time() 223. ]; 224.             db('request_log')->insert($data); 225.             $where =[ 226. ['ip','=',Request::ip()], 227. ['create_time',">=",time()-$this->requestTime] 228. ]; 229.             $list = db('request_log')->where($where)->count('id'); 230. if($list > $this->frequency){ 231.                 $data =[ 232. 'ip'=>Request::ip(), 233. 'domain'=>Request::domain(), 234. 'content'=>'频繁请求', 235. 'create_time'=>  time() 236. ]; 237.                 db('request_blacklist')->insert($data); 238. return['result'=>false,'errorMsg'=>'请求过于频繁,请稍后再进行请求','code'=>200]; 239. } 240. } 242. //验证ip域名白名单 243. if($this->isWhiteList){ 244. //ip,主域名,包含协议域名,请求的url完整路径, 主域名 245.             $requestList =[Request::ip(),Request::host(),Request::domain(),Request::url(true),Request::rootDomain()]; 246. if( empty(array_intersect($this->whiteList, $requestList))){ 247. //读取数据库黑名单表 248.                  $list = db('request_whitelist') 249. ->whereOr('ip','eq',Request::ip()) 250. ->whereOr('domain','eq',Request::domain()) 251. ->whereOr('domain','eq',Request::host()) 252. ->whereOr('domain','eq',Request::rootDomain()) 253. ->whereOr('domain','eq',Request::url(true)) 254. ->find(); 255. if(is_null($list)){ 256. return['result'=>false,'errorMsg'=>'域名[ip]不在白名单中','code'=>200]; 257. } 258. } 259. } 261. //验证设备类型 262. if($this->isDevice){ 263.             $requestDevice =Request::isMobile()?'mobile':'pc'; 264. if(!in_array($requestDevice, $this->device)){ 265. return['result'=>false,'errorMsg'=>'不支持当前设备','code'=>200]; 266. } 267. } 269. //验证终端-- 270. if($this->isTerminal){ 271.             $requestTerminal = $this->getBrowser(); 272. if(!in_array($requestTerminal, $this->terminal)){ 273. return['result'=>false,'errorMsg'=>'不支持当前浏览器','code'=>200]; 274. } 275. } 277. return['result'=>true,'msg'=>'请求通过','code'=>200]; 279. } 281. /** 282.      * 设置 ip 域名 白名单 283.      * @param $blackList array 284.      * @param $isBlackList boolean 285.      */ 286. publicfunction setBlackList($blackList =[], $isBlackList =true) 287. { 288. if(!is_array($blackList)) 289. { 290.             $blackList = explode(",", $blackList); 291. } 293. if(!is_bool($isBlackList)) 294. { 295. thrownewException("参数isBlackList必须是boolean"); 296. } 298.         $this->blackList = array_merge($this->blackList, $blackList); 299.         $this->isBlackList = $isBlackList; 301. return $this; 302. } 304. /** 305.      * 判断是否微信浏览器 306.      */ 307. privatefunction getBrowser() 308. { 309.        $agent   = $_SERVER['HTTP_USER_AGENT']; 310. if(strpos($agent,'MicroMessenger')!==false) 311. { 312. return"weixin"; 313. }elseif(strpos($agent,'QQBrowser')!==false) 314. { 315. return"qq"; 316. }elseif(strpos($_SERVER['HTTP_USER_AGENT'],'UCBrowser')!==false||strpos($_SERVER['HTTP_USER_AGENT'],'UCWEB')!==false) 317. { 318. return"uc"; 319. }elseif(strpos($agent,'baidu')!==false) 320. { 321. return"baidu"; 322. }else 323. { 324. return"other"; 325. } 326. } 328. /** 329.      * 设置是否开启 ajax请求验证 330.      * @param $ajax array [post,get]  331.      * @param $isAjax boolean 332.      */ 333. publicfunction setAjax( $ajax =[],$isAjax =true) 334. { 335. if(!is_array($ajax)){ 336.             $ajax = explode(",", $ajax); 337. } 339. if(!is_bool($isAjax)){ 340. thrownewException("参数isAjax必须是boolean类型"); 341. } 343.         $this->ajax = array_map('strtoupper',$ajax); 344.         $this->isAjax = $isAjax; 346. return $this; 347. } 349. /** 350.      * 设置是否开启 协议验证 351.      * @param $isSsl boolean 352.      */ 353. publicfunction setSsl( $isSsl =true) 354. { 355. if(!is_bool($isSsl)){ 356. thrownewException("参数isSsl必须是boolean类型"); 357. } 359.         $this->isSsl = $isSsl; 361. return $this; 362. } 364. /** 365.      * 设置 频繁请求的参数 366.      * @param $isFrequently 是否开启验证  367.      * @param $requestTime 设置验证的时间数 368.      * @param $frequently 设置在规定的时间内的最大请求数 369.      */ 370. publicfunction setFrequent($requestTime =10, $frequency =50, $isFrequently =true) 371. { 372. if(!is_int($requestTime)||!is_int($frequency)){ 373. thrownewException("参数[requestTime,requestTime]必须是integer类型"); 374. } 376. if(!is_bool($isFrequently)){ 377. thrownewException("参数frequently必须是boolean类型"); 378. } 380.         $this->requestTime = $requestTime; 381.         $this->frequency = $frequency; 382.         $this->isFrequently = $isFrequently; 384. return $this; 385. } 387. /** 388.      * 设置 ip 域名 白名单 389.      * @param $whiteList array 390.      * @param $isWhiteList boolean 391.      */ 392. publicfunction setWhiteList($whiteList =[], $isWhiteList =true) 393. { 394. if(!is_array($whiteList)) 395. { 396.            $whiteList = explode(",", $whiteList); 397. } 399. if(!is_bool($isWhiteList)) 400. { 401. thrownewException("参数isWhiteList必须是boolean"); 402. } 404.         $this->whiteList = array_merge($this->whiteList, $whiteList); 405.         $this->isWhiteList = $isWhiteList; 407. return $this; 408. } 410. /** 411.      * 设置 设备类型 412.      * @param $device array | string  413.      * @param $isDevice 是否开启验证 414.      */ 415. publicfunction setDevice($device =[], $isDevice =true) 416. { 417. if(!is_array($device)) 418. { 419.             $device = explode(",", $device); 420. } 422. if(!is_bool($isDevice)) 423. { 424. thrownewException("参数isDevice必须是boolean"); 425. } 427.         $this->device = $device; 428.         $this->isDevice = $isDevice; 430. return $this; 431. } 433. /** 434.      * 设置 设备类型 435.      * @param $terminal array | string  436.      * @param $isTerminal 是否开启验证 437.      */ 438. publicfunction setTerminal($terminal =[], $isTerminal =true) 439. { 441. if(!is_array($terminal)) 442. { 443.             $terminal = explode(",", $terminal); 444. } 446. if(!is_bool($isTerminal)) 447. { 448. thrownewException("参数isTerminal必须是boolean"); 449. } 451.         $this->terminal = $terminal; 452.         $this->isTerminal = $isTerminal; 454. return $this; 455. } 459. } 复制代码 `暂时记录这些...