PHP编程: Filter 函数(过滤器)高效、安全地获取请求参数

2018-10-2705:42:55编程语言入门到精通Comments3,036 views字数 2883阅读模式

通常,我们获取请求参数的方法为直接访问超全局变量:$_GET,$_POST,$_SERVER,$_ENV,$_COOKIE,而在 php5.2 中,内置了 filter 模块,用于变量的验证和过滤等操作。过滤器函数简化了代码结构,相对于直接访问超全局变量来也更加的高效和安全。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

过滤器函数列表:

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

使用过滤器函数检测是否存在指定类型的变量:

bool filter_has_var(int $type ,string $variable_name);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

其中,type 包含五个常量:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

  • INPUT_GET
  • INPUT_POST
  • INPUT_COOKIE
  • INPUT_SERVER
  • INPUT_ENV

分别对应文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

  • $_GET
  • $_POST
  • $_COOKIE
  • $_SERVER
  • $_ENV

这些常量在其他过滤器函数中同样适用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

filter_has_var() 函数在成功时返回 TRUE,或者在失败时返回 FALSE文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

使用该函数,可以把此段代码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

if (isset($_GET['name'])){
    echo htmlentities($_GET['name']);
} else {
    echo '参数不存在';
}
复制代码

改写为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

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

但是使用此函数,只解决了判断变量是否存在的问题,如果 $name 的值是文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

'jo<br>ne'文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

那么在 echo 的时候会出现显示错误,更严重的是如果对方传过来的 name 中包含了 <script> 标签,就可以对网站进行注入攻击,那么有什么办法来解决这个问题呢?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

通过名称获取特定的外部变量,并且可以通过过滤器处理它:

mixed filter_input ( int $type , string $variable_name [, int $filter = FILTER_DEFAULT [, mixed $options ]] )文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

这个函数可以说是 filter_has_var() 的加强版,它在检测输入是否存在的同时,还可以传入第三个参数(过滤器)来检测该输入是否符合规范,如果变量不存在返回NULL,不符合则返回 FALSE
其中第三个参数需要填一个过滤器类型(默认为 FILTER_SANITIZE_STRING),PHP 有两种过滤器:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

  • Validating 过滤器:
    • 用于验证用户输入
    • 严格的格式规则(比如 URL 或 E-Mail 验证)
    • 如果成功则返回预期的类型,如果失败则返回 FALSE
  • Sanitizing 过滤器:
    • 用于允许或禁止字符串中指定的字符
    • 无数据格式规则
    • 始终返回字符串

例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

$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);
复制代码

当我们使用文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

localhost/test.php?email=1234578<br>qq.com文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

访问包含这段代码的脚本时(显然这是一个非法的email地址),输出如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

VALIDATE:bool(false)
SANITIZE:string(15) "1234578brqq.com"文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

当使用文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

localhost/test.php?email=1234578@qq.com文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

访问时(合法url),输出如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

VALIDATE:string(14) "1234578@qq.com"
SANITIZE:string(14) "1234578@qq.com"文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

很明显,当参数的值合法时,两个过滤器会返回相同的值,但是当参数非法时,VALIDATE 会返回一个布尔值 FALSE,而 SANITIZE 返回了一个过滤掉特殊字符的字符串。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

值得一提的是,可以传入 FILTER_VALIDATE_REGEXP 参数,从而根据 regexp,兼容 Perl 的正则表达式来验证值:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

$options = ['options'=>['default'=>'', 'regexp'=>"/^\w*$/"]];
$xxx = filter_input(INPUT_GET,'xxx', FILTER_VALIDATE_REGEXP, $options);
复制代码

所以,VALIDATE 类型的过滤器适合用来判断格式是否正确,而 SANITIZE 能够对给定的字符串进行过滤(具体过滤规则请参考:php.net/manual/zh/f…)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

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

使用回调函数:FILTER_CALLBACK

如果你看系统自带的过滤器都不顺眼,那你可以将第三个参数指定为 FILTER_CALLBACK ,并在第四个参数的位置指定一个回调函数,来实现自己的过滤器,格式如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

filter_input(INPUT_POST, 'email',FILTER_CALLBACK,array('options' => 'my_filter'));
复制代码

回调函数格式如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

function my_filter($str)
{
	// 需要一个形参(本例中为 $str)来接受字符串
	// 拿到目标字符串后就可以对它为所欲为了
	$str .= 'f*ck';
	// 最后记得 return 加工后的字符串
	return $str;
}
复制代码

扩展应用

相信你也发现了,这只是 PHP 的过滤器函数中的一部分,如果你的目标字符串不是来源于前端输入,而是后端自己加工(或是从数据库直接取出)出来的,同样也可以使用类似的过滤器函数,如 filter_var(),该函数的语法为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

filter_var(variable, filter, options); 可以看到,和我们上面使用的函数大同小异,你只需要在传入输入类型的地方改为传入一个要过滤的变量就可以了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

作者:Gtaker
链接:https://juejin.im/post/5b4317296fb9a04f9d1bd548
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/7272.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/7272.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定