背景

  在上次项目的时候,一直不明白为什么要对数据验证,我能保证我每次请求的数据都是合法的,但是在后面的时候,原来“用户”并不是那样听话,他总是要给我们找麻烦,然后可能让我们的服务器崩掉。但是只对单个请求做数据验证,不能很好的统一管理,所有就想到了将验证信息提出来。以后每次直接调用就好。

验证类 Validator.class.php

该验证类中加入了XSS过滤,可以对参数进行过滤后验证,实现数据合理化 也可以调用setXss(false)关闭XSS过滤

  1. <?php
  2.  
  3. /*************************************************
  4. Validator for PHP 服务器端 【验证数据】
  5. code by HoldKing
  6. date:2016-06-01
  7. *************************************************/
  8.  
  9. class Validator{
  10.  
  11. private static $_instance; //保存类实例的静态成员变量
  12. private $error_msg = []; // 错误提示信息
  13. private $xss = true; // 是否进行XSS的过滤
  14.  
  15. //private标记的构造方法
  16. private function __construct(){
  17. // echo 'This is a Constructed method. ';
  18. }
  19.  
  20. //创建__clone方法防止对象被复制克隆
  21. public function __clone(){
  22. die('Validator Clone is not allow!');
  23. }
  24.  
  25. //单例方法,用于访问实例的公共的静态方法
  26. public static function getInstance(){
  27. if(!(self::$_instance instanceof self)){
  28. self::$_instance = new self;
  29. }
  30. return self::$_instance;
  31. }
  32.  
  33. //是否进行XSS的过滤
  34. public function setXss($xss){
  35. $this->xss = $xss;
  36. }
  37.  
  38. private function remove_xss($string) {
  39. if( empty($string) ) return $string;
  40. if( !$this->valiUrl($string) ) return $string;
  41.  
  42. if( strstr($string, '%25') ){ $string = urldecode($string); }
  43. $string = urldecode($string);
  44.  
  45. $string = preg_replace('/<script[\w\W]+?<\/script>/si', '', $string);
  46. $string = preg_replace("/'.*?'/si", '', preg_replace('/".*?"/si', '', $string) );
  47.  
  48. $string = strip_tags ( trim($string) );
  49. $string = str_replace ( array ('"', "'", "\\", "..", "../", "./", "//", '/', '>'), '', $string );
  50.  
  51. $string = preg_replace ( '/%0[0-8bcef]/', '', $string );
  52. $string = preg_replace ( '/%1[0-9a-f]/' , '', $string );
  53. $string = preg_replace ( '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $string );
  54.  
  55. return $string;
  56. }
  57.  
  58. /*
  59. * 添加数据与验证规则
  60. * @param array $data 验证数据源 [&引用传递]
  61. * @param array $gule 验证数据规则
  62. */
  63. public function make(array &$data, array $gules){
  64.  
  65. if( !is_array($data) ){
  66. $this->error_msg['datas'] = 'The datas is not array.';
  67. return false;
  68. }
  69.  
  70. if( !is_array($gules) ){
  71. $this->error_msg['gules'] = 'The gules is not array.';
  72. return false;
  73. }
  74.  
  75. foreach($gules as $name => $gule){
  76. if( !isset($data[$name]) ){
  77. $this->error_msg[$name] = "We need to $name field in the datas";
  78. continue ;
  79. }
  80.  
  81. if($this->xss){ // xss 过滤
  82. $data[$name] = $this->remove_xss($data[$name]);
  83. }
  84.  
  85. $this->valiRun($gule, $data[$name], $name);
  86. }
  87.  
  88. }
  89.  
  90. /*
  91. * 查看是否有验证错误
  92. * return bool
  93. */
  94. public function fails(){
  95. return count($this->error_msg);
  96. }
  97.  
  98. /*
  99. * 查看是否有验证错误
  100. * return array
  101. */
  102. public function error(){
  103. return $this->error_msg;
  104. }
  105.  
  106. /*
  107. * 对数据进行验证规则验证
  108. * @param int|string|... $data 验证数据
  109. * @param string $gule 验证规则字符串
  110. * @param string $name 验证数据键名
  111. * return bool
  112. */
  113. private function valiRun($gule, $data, $name){
  114. // 拆分多个验证规则
  115. $gule = explode('|', $gule);
  116. foreach($gule as $method){
  117.  
  118. @list($method, $param) = explode(':', $method);
  119. $valiMethod = 'vali' . ucwords($method) ;
  120. if( method_exists($this, $valiMethod) ){
  121. if( $this->$valiMethod($data, $param) ){
  122. $this->doMessage($name, $method, $param);
  123. break ;
  124. }
  125. continue ;
  126. }
  127.  
  128. $this->error_msg[$name] = "Method [$method] does not exist.";
  129. }
  130. }
  131.  
  132. private function doMessage($attribute, $method, $param = ''){
  133. if( $param == '' ){
  134. $this->error_msg[$attribute] = "The $attribute field must be $method.";
  135. }else{
  136. $param = str_replace(':attribute', $attribute, $param);
  137. $this->error_msg[$attribute] = $param;
  138. }
  139. }
  140.  
  141. /********** 规则验证 直接验证 *************/
  142. private function valiRequired($str, $param=null){
  143. return empty($str);
  144. }
  145. private function valiString($str, $param=null){
  146. return !is_string($str);
  147. }
  148. private function valiInt($str, $param=null){
  149. return $str != (int)$str;
  150. }
  151. private function valiNumeric($str, $param=null){
  152. return !is_numeric($str);
  153. }
  154. private function valiArray($str, $param=null){
  155. return !is_array($str);
  156. }
  157. private function valiEmail($str, $param=null){
  158. return !preg_match("/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/", $str);
  159. }
  160. private function valiUrl($str, $param=null){
  161. return !preg_match("/^https?:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"])*$/", $str);
  162. }
  163. private function valiQq($str, $param=null){
  164. return !preg_match("/^[1-9]\d{4,8}$/", $str);
  165. }
  166. private function valiZip($str, $param=null){
  167. return !preg_match("/^[1-9]\d{5}$/", $str);
  168. }
  169. private function valiIdcard($str, $param=null){
  170. return !preg_match("/^\d{17}[X0-9]$/", $str);
  171. }
  172. private function valiChinese($str, $param=null){
  173. return !ereg("^[".chr(0xa1)."-".chr(0xff)."]+$", $str);
  174. }
  175. private function valiMobile($str, $param=null){
  176. return !preg_match("/^((\(\d{3}\))|(\d{3}\-))?13\d{9}$/", $str);
  177. }
  178. private function valiPhone($str, $param=null){
  179. return !preg_match("/^((\(\d{3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}$/", $str);
  180. }
  181. private function valiDate($str, $param=null){
  182. return !preg_match("/^\d{2}(\d{2})?-\d{1,2}-\d{1,2}(\s\d{1,2}:\d{1,2}(:\d{1,2})?)?$/", $str);
  183. }
  184.  
  185. /********** 规则验证 组合验证 *************/
  186. private function valiMin($value, &$param ){
  187. if( !is_numeric($param) ){
  188. $param = "The :attribute need to number"; return true;
  189. }
  190. if($value < $param){
  191. $param = "The :attribute[$value] must be more than $param"; return true;
  192. }
  193. }
  194. private function valiMax($value, &$param){
  195. if( !is_numeric($param) ){
  196. $param = "The :attribute need to number"; return true;
  197. }
  198. if($value > $param){
  199. $param = "The :attribute[$value] must be less than $param"; return true;
  200. }
  201. }
  202. private function valiSize($value, &$param){
  203. if( !is_numeric($param) ){
  204. $param = "The :attribute need to number"; return true;
  205. }
  206. if( strlen($value) != $param ){
  207. $param = "The :attribute[$value] length must be $param"; return true;
  208. }
  209. }
  210. private function valiIn($value, &$param){
  211. $params = explode(',', $param);
  212. if( !is_array($params) || empty($param) || count($params) < 1 ){
  213. $param = "Validation rule in requires at least 1 parameters."; return true;
  214. }
  215. if( !in_array($value, $params) ){
  216. $param = "The :attribute[$value] must be one of the following: $param"; return true;
  217. }
  218. }
  219.  
  220. private function valiBetween($value, &$param){
  221. @list($min, $max) = explode(',', $param);
  222. if( empty($min) || empty($max) ){
  223. $param = "Validation rule between requires at least 2 parameters."; return true;
  224. }
  225. if( $value < $min || $value > $max ){
  226. $param = "The :attribute[$value] must be between $min - $max."; return true;
  227. }
  228. }
  229. private function valiAfter($value, &$param){
  230. if( !$param || !preg_match("/^[\d-]{10}(\s[\d:]{8})?$/", $param) ){
  231. $param = "Validation rule after requires date string."; return true;
  232. }
  233. if( strtotime($value) <= strtotime($param) ){
  234. $param = "The :attribute[$value] must be after $param"; return true;
  235. }
  236. }
  237. private function valiBefore($value, &$param){
  238. if( !$param || !preg_match("/^[\d-]{10}(\s[\d:]{8})?$/", $param) ){
  239. $param = "Validation rule after requires date string."; return true;
  240. }
  241. if( strtotime($value) >= strtotime($param) ){
  242. $param = "The :attribute[$value] must be before $param"; return true;
  243. }
  244. }
  245.  
  246. /******************* 规则验证 end ******************************************/
  247.  
  248. }
  249.  
  250. ?>

使用示例

  1. // 单例模式 获得单例实例
  2. $Validator = Validator::getInstance();
  3.  
  4. // 验证数据源
  5. $input['name'] = 'kingsoft<meta http-equiv="refresh" content="5;">';
  6. $input['age'] = 10;
  7. $input['type'] = "1'%22+onmouseover=alert()+d='%22";
  8. $input['date'] = '2016-05-31 12:26:12"><script>alert(document.cookie)</script><!-';
  9. $input['email'] = 'pengjinping@163.com';
  10. print_r($input);
  11.  
  12. // 开始验证
  13. $Validator->make($input, array(
  14. 'name' => 'required|string|size:4',
  15. 'age' => 'min:5|max:99',
  16. 'email' => 'email',
  17. 'type' => 'in:0,1',
  18. 'date' => 'date'
  19. ));
  20.  
  21. // 判断是否验证通过
  22. if( $Validator->fails() ){
  23. print_r( $Validator->error() );
  24. }
  25.  
  26. // XSS标记被过滤后数据
  27. print_r($input);

运行结果

  1. Array
  2. (
  3. [name] => kingsoft<meta http-equiv="refresh" content="5;">
  4. [age] => 10
  5. [type] => 1'%22+onmouseover=alert()+d='%22
  6. [date] => 2016-05-31 12:26:12"><script>alert(document.cookie)</script><!-
  7. [email] => pengjinping@163.com
  8. )
  9.  
  10. Array
  11. (
  12. [name] => The name[kingsoft] length must be 4
  13. )
  14.  
  15. Array
  16. (
  17. [name] => kingsoft
  18. [age] => 10
  19. [type] => 1
  20. [date] => 2016-05-31 12:26:12
  21. [email] => pengjinping@163.com
  22. )

我们可以看出:

1. name字段没有验证通过,是因为他的长度为8并不是4, 而且支持多种规则验证【组合验证】,这样我们就不用针对不同的情况使用if...else 来判断验证了。

2. 验证结束后的数据与源数据存在差异,我们分析出,这些差异在表单中是不能出现的非法【Xss】攻击数据,所以进行XSS攻击过滤。如果非要使用这些数据内容验证,可以关闭xss过滤,使用原样数据验证。

3. 不支持单个字段关闭xss过滤; 不支持数组字段过滤。

PHP表单数据验证的更多相关文章

  1. php表单数据验证类

    非常好用方便的表单数据验证类 <?php //验证类 class Fun{ function isEmpty($val) { if (!is_string($val)) return false ...

  2. SpringMVC4+thymeleaf3的一个简单实例(篇四:form表单数据验证)

    关于表单数据验证有很多中方法,这里我仅介绍JSR303注解验证.JSR303仅仅是一个规范,这里我们要用到它的一个实现:hibernate-validator. 注意在spring的配置文件sprin ...

  3. struts1:(Struts)ActionForm类及表单数据验证

    在Struts的中央控制器中写了Struts的控制器角色,在这篇介绍下Struts的视图!Struts的视图组件:Struts框架中的视图组件主要包括:JSP页面.ActionForm类.Struts ...

  4. 表单数据验证方法(二)——ASP.NET后台验证

    昨天写了一下关于如何在前台快捷实现表单数据验证的方法,今天接着昨天的,把后台实现数据验证的方法记录一下.先说明一下哈,我用的是asp.net,所以后台验证方法也是基于.net mvc来做的. 好了,闲 ...

  5. Spring学习笔记2——表单数据验证、文件上传

    在上一章节Spring学习笔记1——IOC: 尽量使用注解以及java代码中,已经搭建了项目的整体框架,介绍了IOC以及mybatis.第二节主要介绍SpringMVC中的表单数据验证以及文件上传. ...

  6. jquery表单数据验证扩展方法

    /** 表单数据验证 **/ $.fn.Validform = function () { var Validatemsg = ""; var Validateflag = tru ...

  7. 表单数据验证方法(一)—— 使用validate.js实现表单数据验证

    摘要:使用validate.js在前端实现表单数据提交前的验证 好久没写博客了,真的是罪过,以后不能这样了,只学习不思考,学的都是白搭,希望在博客园能记录下自己学习的点滴,虽然记录的都是些浅显的技术, ...

  8. Angular 开发小妙招1:提交表单数据验证不通过,更改输入组件的样式

    开发表单时,客户端数据完整性校验是必不可少的,在jquery 时代出现了无数的数据验证插件也很好用,开发Angular 应用时,angular 内置了一些常用的数据验证指令.今天要讲的不是这些指令如何 ...

  9. AngularJS 表单数据验证及错误信息提示

    一.表单验证基本原理 表单验证包括两个主题: 定义验证规则,验证数据有效性. 显示验证结果,把验证结果以友好的方式显示给用户. H5内置一些验证功能,并会显示内置的错误提示信息,先要禁用它,在< ...

随机推荐

  1. How to ssh to your Amazon Elastic Beanstalk instance?

    Well, if it's ec2 or a digital ocean server, it would be a lot easier- you do what you normally do f ...

  2. 当我们说线程安全时,到底在说什么——Java进阶系列(二)

    原创文章,同步发自作者个人博客,转载请以超链接形式在文章开头处注明出处http://www.jasongj.com/java/thread_safe/ 多线程编程中的三个核心概念 原子性 这一点,跟数 ...

  3. 【转】oracle in和exists、not in和not exists原理和性能探究

    转自http://www.2cto.com/database/201310/251176.html 对于in和exists.not in和not exists还是有很多的人有疑惑,更有甚者禁用not ...

  4. sql 查看数据库物理文件路径

    方式一:用于查询all数据库,适用于SQL2005及以上版本. USE [Master] GO /****** 对象 :  Table [dbo].[Master]    脚本日期 : 06/29/2 ...

  5. linux vsftp配置

    1.rpm -q ftp 查看是否安装ftp服务器 2.yum install vsftp 安装ftp服务器 3.修改配置文件/etc/vsftpd 下面的 ftpusers和user_list,这两 ...

  6. CE 内存申请

    char ch_ReadByte='H'; char *ptr_OneLineData; unsigned ); if ((ptr_OneLineData = (char *)malloc(bufsi ...

  7. unity官方换装教程Character Customization 学习笔记

    1. 下载示例demo,可以直接从AssetsStore上下载,但是速度比较慢,我在github上找了一个据说支持unity5.x的. 链接:https://github.com/spacebeagl ...

  8. 排序算法练习--JAVA(插入、直接选择、冒泡、快速排序、非递归快速排序)

    排序算法是数据结构中的经典算法知识点,也是笔试面试中经常考察的问题,平常学的不扎实笔试时候容易出洋相,回来恶补,尤其是碰到递归很可能被问到怎么用非递归实现... package sort; impor ...

  9. java中的反射,知道类名创建类,还可以设置私有属性的值

    刚刚学到了反射,感觉反射的功能好强大,所以想写篇博客记录下自己的学习成果. 利用反射来创建对象. Class c1=Class.forName("test.Person");//通 ...

  10. GC 源码分析

    java对象的内存分配入口 Hotspot 源码解析(9) •内存代管理器TenuredGeneration对垃圾对象的回收2015-01-18阅读1154 •内存代管理器DefNewGenerati ...