永远不要相信客户端提交的数据,所以对于输入数据的过滤势在必行,我们建议:
- 开启令牌验证避免数据的重复提交;
- 使用自动验证和自动完成机制进行初步过滤;
- 使用系统Action类提供的_get _post _cookie等方法获取数据;
- 对用户输入的数据进行有效(根据你的应用)的过滤,常见的安全过滤函数包括stripslashes、htmlentities、htmlspecialchars等,官方的扩展类库中的ORG.Util.Input类则提供了更好的解决方法;
系统变量的全局过滤
系统变量的全局过滤功能,采用VAR_FILTERS 定义,默认为空,表示不进行任何过滤。
如果设置了VAR_FILTERS参数,对GET POST系统变量会进行过滤,例如:
'VAR_FILTERS'=>'htmlspecialchars'
也可以支持多个方法过滤,例如:
'VAR_FILTERS'=>'stripslashes,strip_tags'
注意如果系统变量存在多维数组的情况,设置的过滤方法要能够很好的支持多维数组过滤。
表单数据合法性检测
使用create方法创建数据对象的时候,可以使用数据的合法性检测,有两种方式:
一、可以配置insertFields 和 updateFields属性可以分别为新增和编辑表单设置insertFields 和 updateFields属性
使用create方法创建数据对象的时候,不在定义范围内的属性将直接丢弃,避免表单提交非法数据。
insertFields 和 updateFields属性的设置采用字符串(逗号分割多个字段)或者数组的方式。
设置的字段应该是实际的数据表字段,而不受字段映射的影响。例如:
class UserModel extends Model{
protected $insertFields = array('account','password','nickname','email');
protected $updateFields = array('nickname','email');
}
定义后,调用add方法写入用户数据的时候,只能写入'account','password','nickname','email' 这几个字段,编辑的时候只能更新'nickname','email'两个字段。
在使用的时候,我们调用create方法的时候,会根据提交类型自动识别insertFields和updateFields属性:
D('User')->create();
二、直接调用field方法如果不想定义insertFields和updateFields属性,可以在调用create方法之前直接调用field方法,例如,实现和上面的例子同样的作用:
在新增用户数据的时候,使用:
M('User')->field('account,password,nickname,email')->create();
而在更新用户数据的时候,使用:
M('User')->field('nickname,email')->create();
这里的字段也是实际的数据表字段。
field方法也可以使用数组方式。
使用字段合法性检测后,你不再需要担心用户在提交表单的时候注入非法字段数据了。
写入数据过滤
可以在数据写入数据库之前调用filter方法对数据进行安全过滤,例如:
$this->data($data)->filter('strip_tags')->add();