PHP表单数据验证
背景:
在上次项目的时候,一直不明白为什么要对数据验证,我能保证我每次请求的数据都是合法的,但是在后面的时候,原来“用户”并不是那样听话,他总是要给我们找麻烦,然后可能让我们的服务器崩掉。但是只对单个请求做数据验证,不能很好的统一管理,所有就想到了将验证信息提出来。以后每次直接调用就好。
验证类 Validator.class.php
该验证类中加入了XSS过滤,可以对参数进行过滤后验证,实现数据合理化 也可以调用setXss(false)关闭XSS过滤
- <?php
- /*************************************************
- Validator for PHP 服务器端 【验证数据】
- code by HoldKing
- date:2016-06-01
- *************************************************/
- class Validator{
- private static $_instance; //保存类实例的静态成员变量
- private $error_msg = []; // 错误提示信息
- private $xss = true; // 是否进行XSS的过滤
- //private标记的构造方法
- private function __construct(){
- // echo 'This is a Constructed method. ';
- }
- //创建__clone方法防止对象被复制克隆
- public function __clone(){
- die('Validator Clone is not allow!');
- }
- //单例方法,用于访问实例的公共的静态方法
- public static function getInstance(){
- if(!(self::$_instance instanceof self)){
- self::$_instance = new self;
- }
- return self::$_instance;
- }
- //是否进行XSS的过滤
- public function setXss($xss){
- $this->xss = $xss;
- }
- private function remove_xss($string) {
- if( empty($string) ) return $string;
- if( !$this->valiUrl($string) ) return $string;
- if( strstr($string, '%25') ){ $string = urldecode($string); }
- $string = urldecode($string);
- $string = preg_replace('/<script[\w\W]+?<\/script>/si', '', $string);
- $string = preg_replace("/'.*?'/si", '', preg_replace('/".*?"/si', '', $string) );
- $string = strip_tags ( trim($string) );
- $string = str_replace ( array ('"', "'", "\\", "..", "../", "./", "//", '/', '>'), '', $string );
- $string = preg_replace ( '/%0[0-8bcef]/', '', $string );
- $string = preg_replace ( '/%1[0-9a-f]/' , '', $string );
- $string = preg_replace ( '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $string );
- return $string;
- }
- /*
- * 添加数据与验证规则
- * @param array $data 验证数据源 [&引用传递]
- * @param array $gule 验证数据规则
- */
- public function make(array &$data, array $gules){
- if( !is_array($data) ){
- $this->error_msg['datas'] = 'The datas is not array.';
- return false;
- }
- if( !is_array($gules) ){
- $this->error_msg['gules'] = 'The gules is not array.';
- return false;
- }
- foreach($gules as $name => $gule){
- if( !isset($data[$name]) ){
- $this->error_msg[$name] = "We need to $name field in the datas";
- continue ;
- }
- if($this->xss){ // xss 过滤
- $data[$name] = $this->remove_xss($data[$name]);
- }
- $this->valiRun($gule, $data[$name], $name);
- }
- }
- /*
- * 查看是否有验证错误
- * return bool
- */
- public function fails(){
- return count($this->error_msg);
- }
- /*
- * 查看是否有验证错误
- * return array
- */
- public function error(){
- return $this->error_msg;
- }
- /*
- * 对数据进行验证规则验证
- * @param int|string|... $data 验证数据
- * @param string $gule 验证规则字符串
- * @param string $name 验证数据键名
- * return bool
- */
- private function valiRun($gule, $data, $name){
- // 拆分多个验证规则
- $gule = explode('|', $gule);
- foreach($gule as $method){
- @list($method, $param) = explode(':', $method);
- $valiMethod = 'vali' . ucwords($method) ;
- if( method_exists($this, $valiMethod) ){
- if( $this->$valiMethod($data, $param) ){
- $this->doMessage($name, $method, $param);
- break ;
- }
- continue ;
- }
- $this->error_msg[$name] = "Method [$method] does not exist.";
- }
- }
- private function doMessage($attribute, $method, $param = ''){
- if( $param == '' ){
- $this->error_msg[$attribute] = "The $attribute field must be $method.";
- }else{
- $param = str_replace(':attribute', $attribute, $param);
- $this->error_msg[$attribute] = $param;
- }
- }
- /********** 规则验证 直接验证 *************/
- private function valiRequired($str, $param=null){
- return empty($str);
- }
- private function valiString($str, $param=null){
- return !is_string($str);
- }
- private function valiInt($str, $param=null){
- return $str != (int)$str;
- }
- private function valiNumeric($str, $param=null){
- return !is_numeric($str);
- }
- private function valiArray($str, $param=null){
- return !is_array($str);
- }
- private function valiEmail($str, $param=null){
- return !preg_match("/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/", $str);
- }
- private function valiUrl($str, $param=null){
- return !preg_match("/^https?:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"])*$/", $str);
- }
- private function valiQq($str, $param=null){
- return !preg_match("/^[1-9]\d{4,8}$/", $str);
- }
- private function valiZip($str, $param=null){
- return !preg_match("/^[1-9]\d{5}$/", $str);
- }
- private function valiIdcard($str, $param=null){
- return !preg_match("/^\d{17}[X0-9]$/", $str);
- }
- private function valiChinese($str, $param=null){
- return !ereg("^[".chr(0xa1)."-".chr(0xff)."]+$", $str);
- }
- private function valiMobile($str, $param=null){
- return !preg_match("/^((\(\d{3}\))|(\d{3}\-))?13\d{9}$/", $str);
- }
- private function valiPhone($str, $param=null){
- return !preg_match("/^((\(\d{3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}$/", $str);
- }
- private function valiDate($str, $param=null){
- return !preg_match("/^\d{2}(\d{2})?-\d{1,2}-\d{1,2}(\s\d{1,2}:\d{1,2}(:\d{1,2})?)?$/", $str);
- }
- /********** 规则验证 组合验证 *************/
- private function valiMin($value, &$param ){
- if( !is_numeric($param) ){
- $param = "The :attribute need to number"; return true;
- }
- if($value < $param){
- $param = "The :attribute[$value] must be more than $param"; return true;
- }
- }
- private function valiMax($value, &$param){
- if( !is_numeric($param) ){
- $param = "The :attribute need to number"; return true;
- }
- if($value > $param){
- $param = "The :attribute[$value] must be less than $param"; return true;
- }
- }
- private function valiSize($value, &$param){
- if( !is_numeric($param) ){
- $param = "The :attribute need to number"; return true;
- }
- if( strlen($value) != $param ){
- $param = "The :attribute[$value] length must be $param"; return true;
- }
- }
- private function valiIn($value, &$param){
- $params = explode(',', $param);
- if( !is_array($params) || empty($param) || count($params) < 1 ){
- $param = "Validation rule in requires at least 1 parameters."; return true;
- }
- if( !in_array($value, $params) ){
- $param = "The :attribute[$value] must be one of the following: $param"; return true;
- }
- }
- private function valiBetween($value, &$param){
- @list($min, $max) = explode(',', $param);
- if( empty($min) || empty($max) ){
- $param = "Validation rule between requires at least 2 parameters."; return true;
- }
- if( $value < $min || $value > $max ){
- $param = "The :attribute[$value] must be between $min - $max."; return true;
- }
- }
- private function valiAfter($value, &$param){
- if( !$param || !preg_match("/^[\d-]{10}(\s[\d:]{8})?$/", $param) ){
- $param = "Validation rule after requires date string."; return true;
- }
- if( strtotime($value) <= strtotime($param) ){
- $param = "The :attribute[$value] must be after $param"; return true;
- }
- }
- private function valiBefore($value, &$param){
- if( !$param || !preg_match("/^[\d-]{10}(\s[\d:]{8})?$/", $param) ){
- $param = "Validation rule after requires date string."; return true;
- }
- if( strtotime($value) >= strtotime($param) ){
- $param = "The :attribute[$value] must be before $param"; return true;
- }
- }
- /******************* 规则验证 end ******************************************/
- }
- ?>
使用示例
- // 单例模式 获得单例实例
- $Validator = Validator::getInstance();
- // 验证数据源
- $input['name'] = 'kingsoft<meta http-equiv="refresh" content="5;">';
- $input['age'] = 10;
- $input['type'] = "1'%22+onmouseover=alert()+d='%22";
- $input['date'] = '2016-05-31 12:26:12"><script>alert(document.cookie)</script><!-';
- $input['email'] = 'pengjinping@163.com';
- print_r($input);
- // 开始验证
- $Validator->make($input, array(
- 'name' => 'required|string|size:4',
- 'age' => 'min:5|max:99',
- 'email' => 'email',
- 'type' => 'in:0,1',
- 'date' => 'date'
- ));
- // 判断是否验证通过
- if( $Validator->fails() ){
- print_r( $Validator->error() );
- }
- // XSS标记被过滤后数据
- print_r($input);
运行结果
- Array
- (
- [name] => kingsoft<meta http-equiv="refresh" content="5;">
- [age] => 10
- [type] => 1'%22+onmouseover=alert()+d='%22
- [date] => 2016-05-31 12:26:12"><script>alert(document.cookie)</script><!-
- [email] => pengjinping@163.com
- )
- Array
- (
- [name] => The name[kingsoft] length must be 4
- )
- Array
- (
- [name] => kingsoft
- [age] => 10
- [type] => 1
- [date] => 2016-05-31 12:26:12
- [email] => pengjinping@163.com
- )
我们可以看出:
1. name字段没有验证通过,是因为他的长度为8并不是4, 而且支持多种规则验证【组合验证】,这样我们就不用针对不同的情况使用if...else 来判断验证了。
2. 验证结束后的数据与源数据存在差异,我们分析出,这些差异在表单中是不能出现的非法【Xss】攻击数据,所以进行XSS攻击过滤。如果非要使用这些数据内容验证,可以关闭xss过滤,使用原样数据验证。
3. 不支持单个字段关闭xss过滤; 不支持数组字段过滤。
PHP表单数据验证的更多相关文章
- php表单数据验证类
非常好用方便的表单数据验证类 <?php //验证类 class Fun{ function isEmpty($val) { if (!is_string($val)) return false ...
- SpringMVC4+thymeleaf3的一个简单实例(篇四:form表单数据验证)
关于表单数据验证有很多中方法,这里我仅介绍JSR303注解验证.JSR303仅仅是一个规范,这里我们要用到它的一个实现:hibernate-validator. 注意在spring的配置文件sprin ...
- struts1:(Struts)ActionForm类及表单数据验证
在Struts的中央控制器中写了Struts的控制器角色,在这篇介绍下Struts的视图!Struts的视图组件:Struts框架中的视图组件主要包括:JSP页面.ActionForm类.Struts ...
- 表单数据验证方法(二)——ASP.NET后台验证
昨天写了一下关于如何在前台快捷实现表单数据验证的方法,今天接着昨天的,把后台实现数据验证的方法记录一下.先说明一下哈,我用的是asp.net,所以后台验证方法也是基于.net mvc来做的. 好了,闲 ...
- Spring学习笔记2——表单数据验证、文件上传
在上一章节Spring学习笔记1——IOC: 尽量使用注解以及java代码中,已经搭建了项目的整体框架,介绍了IOC以及mybatis.第二节主要介绍SpringMVC中的表单数据验证以及文件上传. ...
- jquery表单数据验证扩展方法
/** 表单数据验证 **/ $.fn.Validform = function () { var Validatemsg = ""; var Validateflag = tru ...
- 表单数据验证方法(一)—— 使用validate.js实现表单数据验证
摘要:使用validate.js在前端实现表单数据提交前的验证 好久没写博客了,真的是罪过,以后不能这样了,只学习不思考,学的都是白搭,希望在博客园能记录下自己学习的点滴,虽然记录的都是些浅显的技术, ...
- Angular 开发小妙招1:提交表单数据验证不通过,更改输入组件的样式
开发表单时,客户端数据完整性校验是必不可少的,在jquery 时代出现了无数的数据验证插件也很好用,开发Angular 应用时,angular 内置了一些常用的数据验证指令.今天要讲的不是这些指令如何 ...
- AngularJS 表单数据验证及错误信息提示
一.表单验证基本原理 表单验证包括两个主题: 定义验证规则,验证数据有效性. 显示验证结果,把验证结果以友好的方式显示给用户. H5内置一些验证功能,并会显示内置的错误提示信息,先要禁用它,在< ...
随机推荐
- 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 ...
- 当我们说线程安全时,到底在说什么——Java进阶系列(二)
原创文章,同步发自作者个人博客,转载请以超链接形式在文章开头处注明出处http://www.jasongj.com/java/thread_safe/ 多线程编程中的三个核心概念 原子性 这一点,跟数 ...
- 【转】oracle in和exists、not in和not exists原理和性能探究
转自http://www.2cto.com/database/201310/251176.html 对于in和exists.not in和not exists还是有很多的人有疑惑,更有甚者禁用not ...
- sql 查看数据库物理文件路径
方式一:用于查询all数据库,适用于SQL2005及以上版本. USE [Master] GO /****** 对象 : Table [dbo].[Master] 脚本日期 : 06/29/2 ...
- linux vsftp配置
1.rpm -q ftp 查看是否安装ftp服务器 2.yum install vsftp 安装ftp服务器 3.修改配置文件/etc/vsftpd 下面的 ftpusers和user_list,这两 ...
- CE 内存申请
char ch_ReadByte='H'; char *ptr_OneLineData; unsigned ); if ((ptr_OneLineData = (char *)malloc(bufsi ...
- unity官方换装教程Character Customization 学习笔记
1. 下载示例demo,可以直接从AssetsStore上下载,但是速度比较慢,我在github上找了一个据说支持unity5.x的. 链接:https://github.com/spacebeagl ...
- 排序算法练习--JAVA(插入、直接选择、冒泡、快速排序、非递归快速排序)
排序算法是数据结构中的经典算法知识点,也是笔试面试中经常考察的问题,平常学的不扎实笔试时候容易出洋相,回来恶补,尤其是碰到递归很可能被问到怎么用非递归实现... package sort; impor ...
- java中的反射,知道类名创建类,还可以设置私有属性的值
刚刚学到了反射,感觉反射的功能好强大,所以想写篇博客记录下自己的学习成果. 利用反射来创建对象. Class c1=Class.forName("test.Person");//通 ...
- GC 源码分析
java对象的内存分配入口 Hotspot 源码解析(9) •内存代管理器TenuredGeneration对垃圾对象的回收2015-01-18阅读1154 •内存代管理器DefNewGenerati ...