,在IBM DW的http://www.ibm.com/developerworks/cn/opensource/os-php-v522/index.html上有很好的介绍,下面笔记并补充之
过滤扩展功能有两种过滤器:Sanitizing 和 Logical。
Sanitizing 过滤器只是允许或禁止字符串中的字符并将清理后的字符串作为结果返回。无论您将哪种数据格式传入这些函数,它们将始终返回字符串。对于特定类型的使用,这是至关重要的,因为您可以阻止用户发送不适当的输入并导致异常结果。例如,用户可以发现文本块的输入被返回到以下页面上并且要利用那些返回信息。如果清理输入,则将删除输入的所有危险部分。
Logical 过滤器将对变量执行测试并根据测试提供 true 或 false 结果。然后您可以使用结果来决定如何处理数据或获得用户的地址。这种过滤器的简单示例是验证年龄。逻辑测试还可以针对类似 Perl 的正则表达式进行测试。
<?php
echo "You are " . filter_var($_GET['1'], FILTER_SANITIZE_STRING) . ".<br>\n";
echo "Your favorite color is " . filter_var($_GET['2'], FILTER_SANITIZE_STRING) .
".<br>\n";
echo "The airspeed of an unladen swallow is " . filter_var($_GET['3'], FILTER_SANITIZE_STRING)
. ".<br>\n";
?>
用 filter_var()
函数来清理输入并使其有效并且安全。在这种情况下,使用选项 FILTER_SANITIZE_STRING
,该选项将获取输入、删除所有 HTML 标记并选择性地编码或删除特定字符。
由于它将除去 HTML 标记,因此尝试运行 JavaScript 将失败,并且从脚本中获得更适当的结果。
再补充些
PHP: indicates the earliest version of PHP that supports the function.
Function | Description | PHP |
---|---|---|
filter_has_var() | Checks if a variable of a specified input type exist | 5 |
filter_id() | Returns the ID number of a specified filter | 5 |
filter_input() | Get input from outside the script and filter it | 5 |
filter_input_array() | Get multiple inputs from outside the script and filters them | 5 |
filter_list() | Returns an array of all supported filters | 5 |
filter_var_array() | Get multiple variables and filter them | 5 |
filter_var() | Get a variable and filter it | 5 |
PHP Filters
ID Name | Description |
---|---|
FILTER_CALLBACK | Call a user-defined function to filter data |
FILTER_SANITIZE_STRING | Strip tags, optionally strip or encode special characters |
FILTER_SANITIZE_STRIPPED | Alias of "string" filter |
FILTER_SANITIZE_ENCODED | URL-encode string, optionally strip or encode special characters |
FILTER_SANITIZE_SPECIAL_CHARS | HTML-escape '"<>& and characters with ASCII value less than 32 |
FILTER_SANITIZE_EMAIL | Remove all characters, except letters, digits and !#$%&'*+-/=?^_`{|}~@.[] |
FILTER_SANITIZE_URL | Remove all characters, except letters, digits and $-_.+!*'(),{}|\\^~[]`<>#%";/?:@&= |
FILTER_SANITIZE_NUMBER_INT | Remove all characters, except digits and +- |
FILTER_SANITIZE_NUMBER_FLOAT | Remove all characters, except digits, +- and optionally .,eE |
FILTER_SANITIZE_MAGIC_QUOTES | Apply addslashes() |
FILTER_UNSAFE_RAW | Do nothing, optionally strip or encode special characters |
FILTER_VALIDATE_INT | Validate value as integer, optionally from the specified range |
FILTER_VALIDATE_BOOLEAN | Return TRUE for "1", "true", "on" and "yes", FALSE for "0", "false", "off", "no", and "", NULL otherwise |
FILTER_VALIDATE_FLOAT | Validate value as float |
FILTER_VALIDATE_REGEXP | Validate value against regexp, a Perl-compatible regular expression |
FILTER_VALIDATE_URL | Validate value as URL, optionally with required components |
FILTER_VALIDATE_EMAIL | Validate value as e-mail |
FILTER_VALIDATE_IP | Validate value as IP address, optionally only IPv4 or IPv6 or not from private or reserved ranges |
检测判断的例子
1 | <html> |
2 | <head></head> |
3 | <body |
4 | <form action="example04.php" method="post" > |
5 | Enter your age: <input name="age" size="2"> |
6 | <input type="submit" name="submit" value="Go"> |
7 | </form> |
8 | </body> |
9 | </html> |
view plain | print | copy to clipboard | ? |
处理脚本:
1 | <?php |
2 | if (!filter_has_var(INPUT_POST, 'submit')) { |
3 | echo "form"; |
4 | // include the form. |
5 | } |
6 | |
7 | $age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT); |
8 | if (is_null($age)) { |
9 | echo "The 'age' field is required.<br />"; |
10 | } elseif ($age === FALSE) { |
11 | echo "Please enter a valid age.<br />"; |
12 | } else { |
13 | echo "Welcome.<br/>"; |
14 | } |
15 | ?> |
view plain | print | copy to clipboard | ? |
filter_has_var检测给定的变量是否存在。它不会做任何处理只会告诉程序变量是否已经设置。相当于isset($_POST[‘submit’])。filter_input会取得一个变量返回处理好的数据。在上面的例子中会返回一个整数。
如果是要返回一个处于一定范围之内的值,假设是7-77岁之间的人。可以指定一个最大值和一个最小值。
1 | <?php |
2 | if (!filter_has_var(INPUT_POST, 'submit')) { |
3 | echo "form"; |
4 | // include the form. |
5 | } |
6 | $options = array('options'=> array('min_range'=>7, 'min_range'=>77)); |
7 | $age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, $options); |
8 | |
9 | if (is_null($age)) { |
10 | echo "The 'age' field is required.<br />"; |
11 | } elseif ($age === FALSE) { |
12 | echo "You must be enter a valid age and be between 7 and 77 years old.<br />"; |
13 | } else { |
14 | echo "Welcome.<br/>"; |
15 | } |
16 | ?> |
view plain | print | copy to clipboard | ? |
如果是要判断一个有效的邮件地址的话,可以这样:
1 | $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); |
view plain | print | copy to clipboard | ? |
如果邮件地址不正确或者是空的话$email的值将为FALSE。
过滤判断的例子
1 | <html> |
2 | <head></head> |
3 | <body> |
4 | <form action="example05.php" method="post" > |
5 | Enter your name: <input name="name" size="50"> |
6 | <input type="submit" name="submit" value="Go"> |
7 | </form> |
8 | </body> |
9 | </html> |
view plain | print | copy to clipboard | ? |
下面的filter_input函数将自动过滤并返回适当的值:
1 | <?php |
2 | if (!filter_has_var(INPUT_POST, 'submit')) { |
3 | echo "form"; |
4 | // include the form. |
5 | } |
6 | $name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_SPECIAL_CHARS); |
7 | if (is_null($name)) { |
8 | echo "The 'name' field is required.<br />"; |
9 | } else { |
10 | echo "Hello $name.<br/>"; |
11 | } |
12 | ?> |
view plain | print | copy to clipboard | ? |
如果接收到的name值是:
Johnny Weißmüller <b>Jr</b>
FILTER_SANITIZE_SPECIAL_CHARS 将会返回:
Hello Johnny Weißmüller <b>Jr</b>.
一个更好的过滤写法:
1 | $name = filter_input(INPUT_POST, |
2 | 'name', |
3 | FILTER_SANITIZE_STRING, |
4 | FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW); |
view plain | print | copy to clipboard | ? |
输出:
Hello Johnny Weißmüller Jr.
这里的函数还有很多选项,如果你想了解更多的细节可以查看Filter的文档。
如何一次处理所有输入?
1 | <html> |
2 | <head></head> |
3 | <body |
4 | <form action="example07.php" method="post" > |
5 | Name: <input name="name" size="50"><br /> |
6 | Email: <input name="email" size="50"><br /> |
7 | Homepage: <input name="homepage" size="50"><br /> |
8 | Age: <input name="age" size="4"><br /> |
9 | Income: <input name="income" size="50"><br /> |
10 | Your two favourites languages: |
11 | <select name="favourites[]" size="6" multiple> |
12 | <option value="haskell">haskell</option> |
13 | <option value="r">R</option> |
14 | <option value="lua">Lua</option> |
15 | <option value="pike">Pike</option> |
16 | <option value="rebol">Rebol</option> |
17 | <option value="php">PHP</option> |
18 | </select><br /> |
19 | <input type="submit" name="submit" value="Go"> |
20 | </form> |
21 | </body> |
22 | </html> |
view plain | print | copy to clipboard | ? |
处理程序:
1 | <?php |
2 | if (!filter_has_var(INPUT_POST, 'submit')) { |
3 | echo "form"; |
4 | // include the form. |
5 | } |
6 | |
7 | $defs = array( |
8 | 'name' => array('filter'=>FILTER_SANITIZE_STRING, |
9 | 'flags' => FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW), |
10 | 'email' => FILTER_VALIDATE_EMAIL, |
11 | 'homepage' => FILTER_VALIDATE_URL, |
12 | 'age' => array( 'filter' => FILTER_VALIDATE_INT, |
13 | 'options'=> array('min_range'=>7, 'min_range'=>77)), |
14 | 'income' => FILTER_VALIDATE_FLOAT, |
15 | 'favourites' => array( |
16 | 'filter' => FILTER_SANITIZE_STRING, |
17 | 'flags' => FILTER_REQUIRE_ARRAY |
18 | ), |
19 | ); |
20 | |
21 | $input = filter_input_array(INPUT_POST, $defs); |
22 | |
23 | if ($input['age'] === FALSE) { |
24 | exit("You must be between 7 and 77 years old."); |
25 | } |
26 | |
27 | if (is_null($input['favourites'])) { |
28 | exit("You have to choose two or more languages."); |
29 | } |
30 | |
31 | if (!in_array('PHP', $inputs['favourites'])) { |
32 | exit("You don't like PHP!"); |
33 | } |
34 | |
35 | /*Other checks for required values */ |
36 | ?> |
view plain | print | copy to clipboard | ? |
正如上面例子中的,通过一个函数就能处理所有的变量。唯一不同的就是事先定义一个对应的数组。需要注意的是数组中选项的正确性。
这样的做法不但增加了程序的易读性,并且如果要添加移除或者修改处理规则也会非常方便。
更复杂的处理
在下面的处理“favourites”变量时用到了用户自定义函数。"options"指定一个用户自定义函数通过定义callback来实现,语法和PHP的call_user_func一样。
1 | <?php |
2 | class language { |
3 | function __construct($name) { |
4 | $this->name = $name; |
5 | } |
6 | } |
7 | |
8 | function check_languages($var) { |
9 | static $called = 0; |
10 | $called++; |
11 | echo "called: $called: $var<br />"; |
12 | $var = filter_var($var, FILTER_SANITIZE_STRIPPED); |
13 | $l = new language($var); |
14 | return $l; |
15 | } |
16 | |
17 | if (!filter_has_var(INPUT_POST, 'submit')) { |
18 | echo "form"; |
19 | // include the form. |
20 | } |
21 | |
22 | $defs = array( |
23 | 'name' => array('filter'=>FILTER_SANITIZE_STRING, |
24 | 'flags' => FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW), |
25 | 'email' => FILTER_VALIDATE_EMAIL, |
26 | 'homepage' => FILTER_VALIDATE_URL, |
27 | 'age' => FILTER_VALIDATE_INT, |
28 | 'income' => FILTER_VALIDATE_FLOAT, |
29 | 'favourites' => array( |
30 | 'filter' => FILTER_CALLBACK, |
31 | 'options' => 'check_languages' |
32 | ), |
33 | ); |
34 | |
35 | $input = filter_input_array(INPUT_POST, $defs); |
36 | |
37 | if ($input['age'] === FALSE) { |
38 | exit("You must be between 7 and 77 years old."); |
39 | } |
40 | |
41 | if (is_null($input['favourites'])) { |
42 | exit("You have to choose two or more languages."); |
43 | } |
44 | |
45 | echo "Your favourite languages:<br /><ul>"; |
46 | foreach ($input['favourites'] as $l) echo '<li>' . $l->name . "</li>"; |
47 | echo '</ul>'; |
48 | ?> |
view plain | print | copy to clipboard | ? |
如果参数是标准参数,函数将只会别调用一次,如果变量是一个数组,将会自动被数组的每个成员调用一次。
当使用callback的时候Filter不会转换或者验证输入数据。但是上面例子中的filter_var可以在callback函数或者方法中使用。