使用PHP:Filter函数(过滤器)获取参数并进行过滤

通常,我们取得参数的方法为直接访问超全局变量:$_GET,$_POST,$SERVER,$_ENV,$_COOKIE,而在 php5.2 中,内置了filter模块,用于变量的验证和过滤,过滤变量等操作。过滤器函数简化了代码结构,相对于直接访问超全局变量来也更加的高效和安全。


过滤器函数:
filter_has_var — 检测是否存在指定类型的变量
filter_id — 返回与某个特定名称的过滤器相关联的id
filter_input_array — 获取一系列外部变量,并且可以通过过滤器处理它们
filter_input — 通过名称获取特定的外部变量,并且可以通过过滤器处理它
filter_list — 返回所支持的过滤器列表
filter_var_array — 获取多个变量并且过滤它们
filter_var — 使用特定的过滤器过滤一个变量


1,检测是否存在指定类型的变量:

bool filter_has_var(int $type ,string $variable_name)

其中,type包括五个常量: INPUT_GET、INPUT_POST、INPUT_COOKIE、INPUT_SERVER、INPUT_ENV,分别对应$_GET,$_POST,$_COOKIE,$SERVER,$_ENV,这些常量在其他过滤器函数中同样适用

filter_has_var()函数在成功时返回 TRUE,或者在失败时返回 FALSE。

使用该函数,可以把此段代码
if (isset($_GET['name']))
	echo htmlentities($_GET['name']);
else
	echo '参数不存在';

改写为:

echo filter_has_var(INPUT_GET,'name')?$_GET['name']:'参数不存在';

但是使用此函数,只解决了判断变量是否存在的问题,如果name的值是'jo<br>ne',那么在echo的时候会显示错误,更严重的是如果对方使用了<script>标签,就可以对网站进行注入攻击,那么有什么办法来解决这个问题呢?


2,通过名称获取特定的外部变量,并且可以通过过滤器处理它:
mixed filter_input ( int $type , string $variable_name [, int $filter = FILTER_DEFAULT [, mixed $options ]] )


这个函数可以说是filter_has_var()的加强版,它在检测输入是否存在的同时,还可以传入第三个参数( 过滤器)来检测该输入是否符合规范,如果变量不存在返回 NULL,不符合则返回 FALSE

其中第三个参数需要填一个过滤器类型(默认为FILTER_SANITIZE_STRING),php有两种过滤器:


Validating 过滤器:
用于验证用户输入
严格的格式规则(比如 URL 或 E-Mail 验证)
如果成功则返回预期的类型,如果失败则返回 FALSE


Sanitizing 过滤器:

用于允许或禁止字符串中指定的字符
无数据格式规则
始终返回字符串

例:
$email_1 = filter_input(INPUT_GET,'email',FILTER_VALIDATE_EMAIL);
$email_2 = filter_input(INPUT_GET,'email',FILTER_SANITIZE_EMAIL);
echo 'VALIDATE:';var_dump($email_1);
echo "<br>";
echo 'SANITIZE:';var_dump($email_2);


当我们使用 localhost/test.php?email=1234578<br>qq.com访问包含这段代码的脚本时(显然这是一个非法的email地址),输出如下:
VALIDATE:bool(false) 
SANITIZE:string(15) "1234578brqq.com"

当使用 localhost/test.php?email=1234578@qq.com访问时(合法url),输出如下:
VALIDATE:string(14) "1234578@qq.com" 
SANITIZE:string(14) "1234578@qq.com"


很明显, 当参数的值合法时,两个过滤器会返回相同的值,但是当参数非法时,VALIDATE会返回一个布尔值FALSE,而SANITIZE返回了一个过滤掉特殊字符的字符串。


值得一提的是,可以传入 FILTER_VALIDATE_REGEXP参数,从而根据regexp,兼容 Perl 的正则表达式来验证值:
$options = ['options'=>['default'=>'', 'regexp'=>"/^\w*$/"] ];
$xxx = filter_input(INPUT_GET,'xxx', FILTER_VALIDATE_REGEXP, $options);


所以,VALIDATE类型的过滤器适合用来判断格式是否正确,而SANITIZE应该那来对给定的字符串进行过滤(具体过滤规则请参考: http://php.net/manual/zh/filter.filters.sanitize.php)。


同时我们也发现了一个问题,虽然 SANITIZE可以对字符串进行过滤,但是这个过滤非常的简单粗暴, 直接把它看不顺眼字符从字符串中删掉了,这在其他场景中或许大有用处,但在处理输入上,通常我们应该返回给用户一个‘你不能这么做!’的提示,而不应该擅自替用户做其他操作,或者想将那些字符转义并保留下来,如何达到这个目的呢?


使用回调函数:FILTER_CALLBACK

如果你看系统自带的过滤器都不顺眼,那你可以讲第三个参数指定为 FILTER_CALLBACK,并在第四个参数的位置指定一个回调函数,来实现自己的过滤器,格式如下:
filter_input(INPUT_POST, 'email',FILTER_CALLBACK,array('options' => 'my_filter'));

回调函数格式如下:
function my_filter($s){
	//需要一个形参来接受字符串
	//拿到目标字符串后就可以为所欲为了
	//最后记得将加工过的字符串return
	return $s;
	}



扩展应用
相信你也发现了,这只是PHP的过滤器函数中的一部分,如果你的目标字符串不是来源于前端输入,而是后端自己加工(或是从数据库直接取出)出来的,同样也可以使用类似的过滤器函数,如 filter_var(),该函数的语法为:
filter_var(variable, filter, options);
可以看到,和我们上面使用的函数大同小异,你只需要在传入输入类型的地方改为传入一个要过滤的变量就可以了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值