在 WordPress开发过程中验证(Validating)净化(Sanitizing)和转义(Escaping)用户数据

「永远不要相信用户提供的数据」是程序开发的一条黄金原则,一个安全的WordPress主题或插件,或者其他 Web 程序,需要至少做到以下3 点,才能基本保证使用用户数据流程的安全性。

  • 在处理用户输入之前,我们需要验证用户提供的数据,以保证用户提供的数据格式符合我们的要求。
  • 在把用户输入的数据保存在数据库之前,对数据进行净化(消毒)操作,以防一些意外的数据保存在数据库中带来 Bug 或安全文件。
  • 数据库中取出数据,输出到前端的时候,我们还需要对数据进行转义操作,以防止一些意外的字符导致排版的混乱。

处理之前验证(Validating)用户的数据格式

验证数据格式是为了保证用户提交的数据和我们需要的一致,WordPress 提供了几个验证方法来帮助我们进行数据格式验证,具体使用哪个取决于我们需要验证的数据类型。

假如,我们的表单里面有一个文本字段

<input type="text" id="zipcode" name ="zipcode" maxlength ="5"/>

上面的字段中,我们已经用「maxlenght」属性,限制了用户最多输入 5 个字符,但是却没有限制用户可以输入什么类型的字符,用户可以输入 “12345” 或者 “abcde”,但是邮编都是数字类型的数据,如果用户输入了非数字的字符,显然是不符合我们要求的。

这个时候,就是验证用户数据的时候,处理表单时,我们需要检查用户提交的每个字段数据是我们需要的格式,这个例子中,我们可以使用下面的代码验证 “zipcode” 字段:

$safe_zipcode = intval($_POST ['zipcode']);
if(!$safe_zipcode){
  $safe_zipcode = '';
}

if(strlen($safe_zipcode)> 5){
  $safe_zipcode = substr($safe_zipcode,0,5);
}

update_post_meta($post-> ID,'zipcode',$safe_zipcode);

表单的「maxlenght」属性检查仅由浏览器进行,但是有一些浏览器不支持这个属性,用户也可以绕过浏览器检查手动输入更长的字符,所以,即便是前端进行了检查,我们仍然需要在服务器上进行数据检查。

「intval」函数可以将用户输入的数据强制转换为整数,如果用户输入的不是整数类型的值,将被转换为 0,然后我们检查该值是否为 0,就知道用户输入的数据是否有效了。

这种验证风格最接近 WordPress 的白名单理念:只允许用户输入您期望的内容。WordPress 提供了很多方便的辅助函数来帮助我们处理大多数数据类型。

保存到数据库之前净化(Sanitizing)用户数据

和上面的数据验证对比,净化(消毒)用户数据使用起来比较自由,当我们对用户输入的数据格式要求不是那么严格时,我们可以调用这些方法来净化用户输入的数据。

例如,我们的表单中有这样一个字段:

<input type="text" id="title" name="title" />

我们可以使用 sanitize_text_field() 函数来清理用户输入数据中不符合要求的字符。

$title = sanitize_text_field( $_POST['title'] );
update_post_meta( $post->ID, 'title', $title );

这个函数在背后默默的帮我们做了很多事情,大致如下:

  • 检查无效的UTF-8(使用 wp_check_invalid_utf8 函数)
  • 将单个 < 字符转换为 HTML 实体
  • 删除所有标签
  • 删除换行符,标签和额外的空白区域
  • 删除八字节字符

除了 sanitize_text_field 函数,我们还可以使用下面的函数来净化用户提供的数据。

  • sanitize_email() 删除电子邮件地址中不允许使用的所有字符
  • sanitize_file_name() 删除文件名中不允许使用的所有字符
  • sanitize_html_class() 清理html类名以确保它只包含有效字符
  • sanitize_key() 清理不能作为数据键使用的所有字符
  • sanitize_meta() 清理不能作为自定义字段使用的所有字符
  • sanitize_mime_type() 清理不是 Mime 类型的所有字符
  • sanitize_option() 根据选项的性质清理各种选项值
  • sanitize_sql_orderby() 清理 SQL orderby 属性
  • sanitize_text_field() 清理用户输入为纯文本字段
  • sanitize_textarea_field() 清理用户输入为纯文本字段,但是保留换行符
  • sanitize_title() 清理转换用户输入为符合文章别名使用的数据
  • sanitize_title_for_query() 清理用户输入为符合文章别名的格式,上下文为 「query」,用于使用该数据从数据中查询数据。
  • sanitize_title_with_dashes() 清理标题,用破折号替换空格。
  • sanitize_user() 清理用户数据的数据为符合 WordPress 用户名的数据

输出时转义(Escaping)用户数据

为了防止输出无效数据带来的问题,我们在输出用户提供的数据时,需要把需要输出的数据进行转义。WordPress 为我们提供了几个转义函数来帮助我们转义以下几种类型的数据。

esc_html() 在使用 HTML 包裹我们需要输出的数据时,应该使用此函数对数据进行转义,以防数据中的 HTML 表单破坏 HTML 结构,造成排版混乱。该函数使用方法如下:

<h4><?php echo esc_html( $title ); ?></h4>

esc_url() 当我们需要输出一个 URL 字符串时,应该使用此函数对数据进行转义,如 src 和 href 属性的 URL。

<img src="<?php echo esc_url( $great_user_picture_url ); ?>" />

esc_js() 用于转换内联 JavaScript 代码,如下:

<a href="#" onclick="<?php echo esc_js( $custom_js ); ?>">Click me</a>

esc_attr() 当我们需要输出用户数据作为 HTML 元素的属性值时,我们可是使用这个函数掉用户数据进行转义。如下:

<ul class="<?php echo esc_attr( $stored_class ); ?>">

esc_textarea() 对文本进行转义,以便在textarea元素中使用。

<textarea><?php echo esc_textarea( $text ); ?></textarea>

是否对用户提供的数据进行合适的处理是判断一个WordPress主题和插件是否优秀的基本标准,在WordPress主题开发和WordPress插件开发的时候,主要涉及到需要处理用户数据的地方,我们就要考虑使用验证、净化、转义操作来保证安全性,这样才能尽量减少插件的 Bug 和安全漏洞,开发出优秀稳定的主题或插件。

发布评论