PHP 7: 真实世界的应用开发
  • 前言
  • 模块一
    • 第一章、建立基础
      • PHP 7 安装注意事项
      • 使用内置的 PHP web 服务器
      • 创建一个 MySQL 测试数据库
      • 安装 PHPUnit
      • 实现类的自动加载
      • 抓取一个网站
      • 建立一个深度网络扫描器
      • 创建一个 PHP 5 到 PHP 7 代码转换器
    • 第二章、使用 PHP 7 高性能特性
      • 了解抽象语法树
      • 理解句法分析中的差异
      • 理解 foreach() 处理中的差异
      • 使用 PHP 7 增强功能提高性能
      • 遍历海量文件
      • 将电子表格上传到数据库
      • 递归目录迭代器
    • 第三章、使用 PHP 函数
      • 函数开发
      • 数据类型提示
      • 使用返回值数据类型
      • 使用迭代器
      • 使用生成器编写自己的迭代器
    • 第四章、使用 PHP 面向对象程序设计
      • 类的开发
      • 类的扩展
      • 使用静态属性和方法
      • 使用命名空间
      • 定义可见性
      • 使用接口
      • 使用特性
      • 实现匿名类
    • 第五章、与数据库的交互
      • 使用PDO连接数据库
      • 构建一个 OOP SQL 查询生成器
      • 处理分页
      • 定义实体以匹配数据库表
      • 将实体类与RDBMS查询绑定
      • 将二次查找嵌入到查询结果中
      • 实现jQuery DataTables的PHP查找
    • 第六章、建立可扩展的网站
      • 创建通用表单元素生成器
      • 创建一个HTML单选元素生成器
      • 创建一个HTML选择元素生成器
      • 实现表单工厂
      • 链式 $_POST 过滤器
      • 链式 $_POST 验证器
      • 将验证绑定到表单
    • 第七章、访问Web服务
      • 在PHP和XML之间转换
      • 创建一个简单的REST客户端
      • 创建一个简单的REST服务器
      • 创建一个简单的SOAP客户端
      • 创建一个简单的SOAP服务器
    • 第八章、处理日期/时间和国际化方面
      • 在视图脚本中使用 emoji
      • 转换复杂字符
      • 从浏览器数据获取语言环境
      • 按地区设置数字格式
      • 按地区处理货币
      • 按地区设置日期/时间格式
      • 创建一个HTML国际日历生成器
      • 构建一个周期性事件生成器
      • 不使用gettext处理翻译
    • 第九章、开发中间件
      • 使用中间件进行认证
      • 使用中间件实现访问控制
      • 使用高速缓存提高性能
      • 实施路由选择
      • 进行框架间的系统调用
      • 使用中间件来跨语言
    • 第十章、高级算法
      • 使用 getter 和 setter
      • 实现一个链表
      • 建立冒泡排序
      • 实现一个堆栈
      • 构建一个二分法查找类
      • 实现一个搜索引擎
      • 显示多维数组并累计总数
    • 第十一章、软件设计模式的实现
      • 创建数组到对象的转化器
      • 构建对象到数组到转化器
      • 实施策略模式
      • 定义一个映射器
      • 实现对象关系映射
      • 实施发布/订阅设计模式
    • 第十二章、提高网站安全
      • 过滤$_POST数据
      • 验证$_POST数据
      • 保护PHP session
      • 用令牌保护表格的安全
      • 建立一个安全的密码生成器
      • 带有验证码的安全保护表格
      • 不使用mcrypt进行加密/解密
    • 第十三章、最佳实践、测试和调试
      • 使用特征和接口
      • 通用异常处理程序
      • 通用错误处理程序
      • 编写一个简单的测试
      • 编写测试套件
      • 生成虚假的测试数据
      • 使用session_start参数自定义会话
    • PSR-7
  • 模块二
  • 模块三
    • GoF 设计模式
      • 结构型
      • 行为型
      • 小结
    • SOLID 设计原则
      • 开闭原则
      • 里氏替换原则
      • 接口隔离原则
      • 依赖反转原则
      • 小结
    • 模块化网店应用的需求规范
      • 线框设计
      • 定义技术栈
      • 小结
    • Symfony 概述
      • 创建一个空白项目
      • 使用 Symfony 控制台
      • 控制器
      • 路由
      • 模板
      • 表单
      • 配置 Symfony
      • bundle 系统
      • 数据库和 Doctrine
      • 测试
      • 验证
      • 小结
    • 构建核心模块
    • 构建目录模块
    • 构建客户模块
    • 构建支付模块
    • 构建发货模块
    • 构建销售模块
    • 总结
由 GitBook 提供支持
在本页
  • 如何做...
  • 如何运行...
  1. 模块一
  2. 第十二章、提高网站安全

过滤$_POST数据

过滤数据的过程可以包括以下任何或全部内容:

  • 删除不需要的字符(即删除<script>标签)

  • 对数据进行转换(即,将报价转换为 &quot;)

  • 对数据进行加密或解密

加密的内容在本章的最后一个示例中介绍。除此之外,我们将介绍一个基本的机制,可以用来过滤表单提交后到达的$_POST数据。

如何做...

1.首先,你需要对$_POST中的数据有一个认识。另外,也许更重要的是,您需要了解存储表格数据的数据库表所施加的限制。举个例子,看看prospects表的数据库结构。

COLUMN          TYPE              NULL   DEFAULT
first_name      varchar(128)      No     None     NULL
last_name       varchar(128)      No     None     NULL
address         varchar(256)      Yes    None     NULL
city            varchar(64)       Yes    None     NULL
state_province  varchar(32)       Yes    None     NULL
postal_code     char(16)          No     None     NULL
phone           varchar(16)       No     None     NULL
country         char(2)           No     None     NULL
email           varchar(250)      No     None     NULL
status          char(8)           Yes    None     NULL
budget          decimal(10,2)     Yes    None     NULL
last_updated    datetime          Yes    None     NULL

2. 一旦你完成了对要发布和存储的数据的分析,你就可以确定要进行哪种类型的过滤,哪些PHP函数可以达到这个目的。

3.例如,如果你需要去除用户提供的表单数据中的开头和结尾空白,你可以使用PHP的trim()函数。根据数据库结构,所有的字符数据都有长度限制。因此,你可以考虑使用substr()来确保长度不被超过。如果你想删除非字母字符,你可以考虑使用preg_replace()配合适当的模式来删除。

4. 现在我们可以将所需的PHP函数集归为一个回调数组。下面是一个基于表单数据过滤需求的例子,这些数据最终将被存储在prospector表中。

$filter = [
  'trim' => function ($item) { return trim($item); },
  'float' => function ($item) { return (float) $item; },
  'upper' => function ($item) { return strtoupper($item); },
  'email' => function ($item) { 
     return filter_var($item, FILTER_SANITIZE_EMAIL); },
  'alpha' => function ($item) { 
     return preg_replace('/[^A-Za-z]/', '', $item); },
  'alnum' => function ($item) { 
     return preg_replace('/[^0-9A-Za-z ]/', '', $item); },
  'length' => function ($item, $length) { 
     return substr($item, 0, $length); },
  'stripTags' => function ($item) { return strip_tags($item); },
];

5. 接下来,我们定义一个与$_POST中预期的字段名相匹配的数组。在这个数组中,我们指定了$filter数组中的键,以及任何参数。注意第一个键*。我们将使用它作为通配符应用于所有字段。

$assignments = [
  '*'             => ['trim' => NULL, 'stripTags' => NULL],
  'first_name'    => ['length' => 32, 'alnum' => NULL],
  'last_name'     => ['length' => 32, 'alnum' => NULL],
  'address'       => ['length' => 64, 'alnum' => NULL],
  'city'          => ['length' => 32],
  'state_province'=> ['length' => 20],
  'postal_code'   => ['length' => 12, 'alnum' => NULL],
  'phone'         => ['length' => 12],
  'country'       => ['length' => 2, 'alpha' => NULL, 
                      'upper' => NULL],
  'email'         => ['length' => 128, 'email' => NULL],
  'budget'        => ['float' => NULL],
];

6. 然后,我们循环浏览数据集(即来自$_POST),并依次应用回调。我们首先运行所有分配给通配符(*)键的回调。

实现通配符过滤器以避免多余的设置是很重要的。在前面的例子中,我们希望对每个项目应用代表PHP函数strip_tags()和trim()的过滤器。

7. 接下来,我们运行分配给特定数据字段的所有回调。当我们完成后,$data中的所有值将被过滤。

foreach ($data as $field => $item) {
  foreach ($assignments['*'] as $key => $option) {
    $item = $filter[$key]($item, $option);
  }
  foreach ($assignments[$field] as $key => $option) {
    $item = $filter[$key]($item, $option);
  }
}

如何运行...

将步骤4到步骤6中的代码放入一个名为chap_12_post_data_filtering_basic.php的文件中。你还需要定义一个数组来模拟$_POST中的数据. 在这种情况下,你可以定义两个数组,一个是好数据,一个是坏数据。

$testData = [
  'goodData'   => [
    'first_name'    => 'Doug',
    'last_name'     => 'Bierer',
    'address'       => '123 Main Street',
    'city'          => 'San Francisco',
    'state_province'=> 'California',
    'postal_code'   => '94101',
    'phone'         => '+1 415-555-1212',
    'country'       => 'US',
    'email'         => 'doug@unlikelysource.com',
    'budget'        => '123.45',
  ],
  'badData' => [
    'first_name' => 'This+Name<script>bad tag</script>Valid!',
    'last_name' 	=> 'ThisLastNameIsWayTooLongAbcdefghijklmnopqrstuvwxyz0123456789Abcdefghijklmnopqrstuvwxyz0123456789Abcdefghijklmnopqrstuvwxyz0123456789Abcdefghijklmnopqrstuvwxyz0123456789',
    //'address' 	=> '',    // missing
    'city'      => 'ThisCityNameIsTooLong012345678901234567890123456789012345678901234567890123456789  ',
    //'state_province'=> '',    // missing
    'postal_code'     => '!"£$%^Non Alpha Chars',
    'phone'           => ' 12345 ',
    'country'         => '12345',
    'email'           => 'this.is@not@an.email',
    'budget'          => 'XXX',
  ]
];

最后,你需要循环过滤分配,呈现好的和坏的数据。

foreach ($testData as $data) {
  foreach ($data as $field => $item) {
    foreach ($assignments['*'] as $key => $option) {
      $item = $filter[$key]($item, $option);
    }
    foreach ($assignments[$field] as $key => $option) {
      $item = $filter[$key]($item, $option);
    }
    printf("%16s : %s\n", $field, $item);
  }
}

下面是这个例子的输出结果。

请注意,这些名字被截断,标签被删除。您还会注意到,虽然电子邮件地址被过滤,但它仍然不是一个有效的地址。需要注意的是,为了正确处理数据,可能需要验证和过滤。

上一页第十二章、提高网站安全下一页验证$_POST数据

最后更新于4年前