过滤与清理(Filtering and Sanitizing)

清理用户输入是软件开发中很重要的一个环节。信任或者忽略对用户输入数据作清理可能会导致对应用内容(主要是用户数据),甚至你应用所处在的服务器的非法访问。
过滤与清理(Filtering and Sanitizing) - 图1
Full image (from xkcd)

Phalcon\Filter 组件提供了一系列通用可用的过滤器和数据清理助手。它提供了围绕于PHP过滤扩展的面向对象包装。

清理数据(Sanitizing data)

清理是指从一个值中移除特定字符的过程,此过程对用户和应用不是必须,也不是他们想得到的。通过清理输入,我们确保了应用的完整性和正确性。

  1. <?php
  2.  
  3. use Phalcon\Filter;
  4.  
  5. $filter = new Filter();
  6.  
  7. // 返回 "someone@example.com"
  8. $filter->sanitize("some(one)@exa\mple.com", "email");
  9.  
  10. // 返回 "hello"
  11. $filter->sanitize("hello<<", "string");
  12.  
  13. // 返回 "100019"
  14. $filter->sanitize("!100a019", "int");
  15.  
  16. // 返回 "100019.01"
  17. $filter->sanitize("!100a019.01a", "float");

在控制器中使用清理(Sanitizing from Controllers)

当接收到GET或POST的数据时(通过请求对象),你可以在控制器中访问一个 Phalcon\Filter 对象。第一个参数是等待获得变量的名字,第二个参数是将应用在此变量的过滤器。

  1. <?php
  2.  
  3. use Phalcon\Mvc\Controller;
  4.  
  5. class ProductsController extends Controller
  6. {
  7. public function indexAction()
  8. {
  9.  
  10. }
  11.  
  12. public function saveAction()
  13. {
  14. // 从输入中清理price
  15. $price = $this->request->getPost("price", "double");
  16.  
  17. // 从输入中清理email
  18. $email = $this->request->getPost("customerEmail", "email");
  19. }
  20. }

过滤动作参数(Filtering Action Parameters)

接下来的示例演示了在一个控制器的动作中如何清理动作的参数:

  1. <?php
  2.  
  3. use Phalcon\Mvc\Controller;
  4.  
  5. class ProductsController extends Controller
  6. {
  7. public function indexAction()
  8. {
  9.  
  10. }
  11.  
  12. public function showAction($productId)
  13. {
  14. $productId = $this->filter->sanitize($productId, "int");
  15. }
  16. }

过滤数据(Filtering data)

此外, Phalcon\Filter 也提供了可以进行删除或者修改输入数据以满足我们需要的格式的过滤器。函数 sanitize 的第一个参数是用户输入的数据,第二个参数是过滤器名称,第三个参数是是否递归执行,第四个参数是选项值。

  1. <?php
  2.  
  3. use Phalcon\Filter;
  4.  
  5. $filter = new Filter();
  6.  
  7. // 返回 "Hello"
  8. $filter->sanitize("<h1>Hello</h1>", "striptags");
  9.  
  10. // 返回 "Hello"
  11. $filter->sanitize(" Hello ", "trim");
  12.  
  13. // 返回 "Hello"
  14. $filter->sanitize(" Hello ", function($v) {
  15. return trim($v);
  16. });
  17.  
  18. // 返回 NULL
  19. $filter->sanitize("Baidu", "in", NULL, FALSE, ["Google", "Bing"]);
  20.  
  21. // 返回 "Baidu"
  22. $filter->sanitize("Baidu", ["in" => ["Google", "Baidu"]]);

内置过滤器类型(Types of Built-in Filters)

以下是该容器提供的内置过滤器:

名称 描述
string 去除标签和 HTML 实体,包括单双引号
email 删掉除字母、数字和 !#$%&*+-/=?^_`{ }~@.[] 外的全部字符
int 删掉除数字、加号、减号外的全部字符
int! 强制转换为 int 类型
int? 如果是数字字符串,强制转换为 int 类型
abs 将字符串转为 int 或 float,并取绝对值
float 删掉除数字、点号和加号、减号外的全部字符
float! 强制转换为 float 类型
float? 如果是数字字符串,强制转换为 float 类型
alphanum 删掉除[a-zA-Z0-9]外的全部字符
date 安装日期格式 Y-m-d 进行格式过滤
datetime 安装日期格式 Y-m-d 进行格式过滤
url 删除所有非法的 URL 字符
striptags 调用 strip_tags 方法
trim 调用 trim 方法
lower 调用 strtolower 方法
upper 调用 strtoupper 方法
xss 删除所有 script
in 判断是否在设定的数组内

创建过滤器(Creating your own Filters)

你可以将你自己的过滤器添加到 Phalcon\Filter 。过滤器的方法可以是匿名函数:

  1. <?php
  2.  
  3. use Phalcon\Filter;
  4.  
  5. $filter = new Filter();
  6.  
  7. // 使用匿名函数
  8. $filter->add('md5', function ($value) {
  9. return preg_replace('/[^0-9a-f]/', '', $value);
  10. });
  11.  
  12. // 利用md5过滤器清理
  13. $filtered = $filter->sanitize($possibleMd5, "md5");

或者,如果你愿意,你可以在类中实现过滤器:

  1. <?php
  2.  
  3. use Phalcon\Filter;
  4.  
  5. class IPv4Filter
  6. {
  7. public function filter($value)
  8. {
  9. return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
  10. }
  11. }
  12.  
  13. $filter = new Filter();
  14.  
  15. // 使用对象
  16. $filter->add('ipv4', new IPv4Filter());
  17.  
  18. // 利用"ipv4"过滤器清理
  19. $filteredIp = $filter->sanitize("127.0.0.1", "ipv4");

复杂的过滤与清理(Complex Sanitizing and Filtering)

你可以使用PHP本身提供的优秀过滤器扩展。请查看对应的文档: PHP文档上的数据过滤器

自定义过滤器(Implementing your own Filter)

如需创建你自己的过滤器并代替Phalcon提供的过滤器,你需要实现 Phalcon\FilterInterface 接口。

原文: http://www.myleftstudio.com/reference/filter.html