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. }
复制代码
`暂时记录这些...
- 空白目录1
- RBAC
- RBAC权限模型[完整]
- 你知道权限管理的RBAC模型吗?
- rbac 一个用户对应多个账号_如何设计一个强大的权限系统
- Postman 快速使用(设置环境变量)
- postman的使用方法详解!最全面的教程
- Postman常用的几个功能
- ThinkPHP项目总结
- thinkphp5 递归查询所有子代,查询上级,并且获取层级
- PHP原生项目之留言板
- 智慧校园
- PHP如何实现订单的延时处理详解
- VUE
- const {data:res} = await login(this.loginForm)
- Vue中的async和await的使用
- PHP实现消息推送(定时轮询)
- tp5 计算两个日期之间相差的天数
- 使用jquery的ajax方法获取下拉列表值
- jQuery实现select下拉框选中数据触发事件
- SetFocus 方法
- 快来了解下TP6中的超级函数app()!
- PHP socket 服务器框架 workerman
- 程序员如何才能成为独立开发者?
- PHP 错误处理
- php面向对象类中的$this,static,final,const,self及双冒号 :: 这几个关键字使用方法。
- 小白教你玩转php的闭包
- 关于TP6项目搭建的坑(多应用模式)
- ThinkPHP6.0 与5.0的差别及坑点
- axios在vue项目中的使用实例详解
- php中的类、对象、方法是指什么
- 聊一聊PHP的依赖注入(DI) 和 控制反转(IoC)
- 深入理解控制反转(IoC)和依赖注入(DI)
- Private,Public,Protected
- ThinkPHP5(目录,路径,模式设置,命名空间)
- 在 ThinkPHP6 中使用 Workerman
- 介绍thinkphp lock锁的使用和例子
- php中_initialize()函数与 __construct()函数的区别说明
- api接口数据-验证-整理
- api接口数据-验证-整理【续】
- TP6容易踩得坑【原创】
- TP6的日志怎么能记录详细的日志?
- 是否需要模型分层
- PHP面试题 全网最硬核面试题来了 2021年学习面试跳槽必备(一)
- MySQL单表数据量过千万,采坑优化记录,完美解决方案
- MySql表分区(根据时间timestamp)
- MySQL大表优化方案
- 闲言碎语
- 数据库外键的使用
- 深入理解thinkphp、laravel等框架中容器概念
- vue做前端,thinkphp6做后台,项目部署
- 简单MVC架构的PHP留言本
- TP5里面extend和vendor的区别
- 在mysql数据库中制作千万级测试表
- MySQL千万级的大表要怎么优化
- ThinkPHP关联模型操作实例分析
- lcobucci/jwt —— 一个轻松生成jwt token的插件
- RESTful API 设计指南
- MySQL如何为表字段添加索引
- ThinkPHP6.0快速开发手册(案例版)
- tp5 静态方法和普通方法的区别
- 数据字典功能
- mysql中的数据库ID主键的设置问题
- 基于角色的权限控制(django内置auth体系)
- RBAC系统经典五张表
- 什么是接口文档,如何写接口,有什么规范?
- thinkphp5.0自定义验证器