随机数

nonce 是一个“使用过一次的数字”,有助于保护 URL 和表单免受某些类型的滥用、恶意或其他形式的滥用。

从技术上讲,WordPress 随机数并不是严格意义上的数字;它们是由数字和字母组成的散列。它们也不是只使用一次:它们的“生命周期”有限,之后就会过期。在此期间,将在给定上下文中为给定用户生成相同的随机数。在该随机数生命周期完成之前,该操作的随机数对于该用户将保持不变。

WordPress 的安全令牌被称为“nonces”(尽管与真正的 nonces 存在上述差异),因为它们的用途与 nonces 相同。它们有助于防止包括 CSRF 在内的多种类型的攻击,但不能防止重放攻击,因为它们不会被检查一次性使用。永远不应依赖随机数来进行身份验证、授权或访问控制。使用 保护您的功能current_user_can(),并始终假设 nonce 可能会受到损害。

为什么要使用随机数?

关于为什么使用 nonce 的示例,请考虑管理屏幕可能会生成这样的 URL,该 URL 会丢弃帖子编号 123。

http://example.com/wp-admin/post.php?post=123&action=trash

当您转到该 URL 时,WordPress 将验证您的身份验证 cookie 信息,如果您被允许删除该帖子,它将继续删除它。攻击者可以用它做的是让您的浏览器在您不知情的情况下转到该 URL。例如,攻击者可以在 3rd 方页面上制作伪装链接,如下所示:

<img src="http://example.com/wp-admin/post.php?post=123&action=trash" />

这会触发您的浏览器向 WordPress 发出请求,浏览器会自动附加您的身份验证 cookie,而 WordPress 会认为这是一个有效请求。

添加随机数可以防止这种情况。例如,当使用随机数时,WordPress 为用户生成的 URL 如下所示:

http://example.com/wp-admin/post.php?post=123&action=trash&_wpnonce=b192fc4204

如果任何人在没有由 WordPress 生成并提供给用户的正确随机数的情况下试图删除 123 号帖子,WordPress 将向浏览器发送“403 Forbidden”响应。

创建随机数

您可以创建一个随机数并将其添加到 URL 中的查询字符串中,您可以将其添加到表单的隐藏字段中,或者您可以以其他方式使用它。

对于要在 AJAX 请求中使用的随机数,通常将随机数添加到隐藏字段,JavaScript 代码可以从中获取它。

请注意,随机数对于当前用户的会话是唯一的,因此如果用户异步登录或注销,页面上的任何随机数都将不再有效。

将随机数添加到 URL

要将随机数添加到 URL,请调用wp_nonce_url()指定裸 URL 和表示操作的字符串。例如:

$complete_url = wp_nonce_url( $bare_url, 'trash-post_'.$post->ID );

为了获得最大程度的保护,请确保表示操作的字符串尽可能具体。

默认情况下,wp_nonce_url()添加一个名为 的字段_wpnonce。您可以在函数调用中指定不同的名称。例如:

$complete_url = wp_nonce_url( $bare_url, 'trash-post_'.$post->ID, 'my_nonce' );

向表单添加随机数

要将随机数添加到表单,请调用wp_nonce_field()指定表示操作的字符串。默认wp_nonce_field()生成两个隐藏字段,一个值为 nonce,一个值为当前 URL(referrer),并回显结果。例如,这个调用:

wp_nonce_field( 'delete-comment_'.$comment_id );

可能会回应类似的内容:

<input type="hidden" id="_wpnonce" name="_wpnonce" value="796c7766b1" />
<input type="hidden" name="_wp_http_referer" value="/wp-admin/edit-comments.php" />

为了获得最大程度的保护,请确保表示操作的字符串尽可能具体。

您可以为 nonce 字段指定一个不同的名称,您可以指定您不需要 referrer 字段,并且您可以指定您希望返回结果而不是回显。有关语法的详细信息,请参阅:wp_nonce_field()

创建一个以其他方式使用的随机数

要创建以其他方式使用的随机数,请调用wp_create_nonce()指定表示操作的字符串。例如:

$nonce = wp_create_nonce( 'my-action_'.$post->ID );

这只是返回随机数本身。例如:295a686963

为了获得最大程度的保护,请确保表示操作的字符串尽可能具体。

验证随机数

您可以验证在 URL、管理屏幕中的表单、AJAX 请求或其他上下文中传递的随机数。

验证从管理屏幕传递的随机数
要验证在管理屏幕的 URL 或表单中传递的随机数,请调用check_admin_referer()指定表示操作的字符串。

例如:

check_admin_referer( 'delete-comment_'.$comment_id );

此调用检查 nonce 和 referrer,如果检查失败,它会采取正常操作(以“403 Forbidden”响应和错误消息终止脚本执行)。

如果您在创建随机数时未使用默认字段名称 ( _wpnonce),请指定字段名称。

例如:

check_admin_referer( 'delete-comment_'.$comment_id, 'my_nonce' );

验证在 AJAX 请求中传递的随机数

要验证在 AJAX 请求中传递的随机数,请调用check_ajax_referer() 指定表示操作的字符串。例如:

check_ajax_referer( 'process-comment' );

此调用检查 nonce(但不检查 referrer),如果检查失败,则默认情况下它会终止脚本执行。

如果您在创建 nonce 时没有使用默认字段名称(_wpnonce或)之一,或者如果您想采取其他操作而不是终止执行,则可以指定其他参数。_ajax_nonce详情请见:check_ajax_referer()

验证在其他上下文中传递的随机数
要验证在其他上下文中传递的随机数,请wp_verify_nonce()调用指定随机数和表示操作的字符串。

例如:

wp_verify_nonce( $_REQUEST['my_nonce'], 'process-comment'.$comment_id );

如果结果为 false,则不继续处理该请求。相反,采取一些适当的行动。通常的操作是调用wp_nonce_ays(),它向浏览器发送“403 Forbidden”响应。

修改随机数系统

您可以通过添加各种操作和过滤器来修改随机数系统。

修改 nonce 生命周期

默认情况下,随机数的生命周期为一天。之后,即使与操作字符串匹配,随机数也不再有效。要更改生命周期,请添加一个以秒为单位指定生命周期的 nonce_life 过滤器。

例如,将生命周期更改为四个小时:

add_filter( 'nonce_life', function () { return 4 * HOUR_IN_SECONDS; } );

执行附加验证

check_admin_referrer()要在发现 nonce 和 referrer 有效时执行额外验证,请添加一个check_admin_referer操作。

例如:

function wporg_additional_check ( $action, $result ) {
    ...
}
add_action( 'check_admin_referer', 'wporg_additional_check', 10, 2 );

以相同的方式check_ajax_referer()添加一个动作。check_ajax_referer

更改错误消息

您可以使用翻译系统更改随机数无效时发送的错误消息。例如:

function my_nonce_message ($translation) {
    if ($translation === 'Are you sure you want to do this?') {
       return 'No! No! No!';
    } 

    return $translation;
}

add_filter('gettext', 'my_nonce_message');

附加信息

本节包含有关 WordPress 中随机数系统的其他信息,这些信息有时可能会有用。

Nonce 生命周期

请注意,正如 WordPress 随机数不是“使用一次的数字”一样,随机数生命周期也不是真正的随机数生命周期。WordPress 使用一个有两个 tick(生命周期的一半)的系统,并从当前 tick 和最后一个 tick 验证随机数。在默认设置(24 小时生命周期)中,这意味着随机数中的时间信息与自 Unix 纪元以来经过了多少个 12 小时的时间段有关。这意味着在中午和午夜之间创建的随机数将一直持续到第二天中午。因此,实际寿命在 12 到 24 小时之间变化。

当 nonce 有效时,验证 nonce 的函数返回当前的 tick 号 1 或 2。例如,您可以使用此信息来刷新处于第二个 tick 的 nonce,这样它们就不会过期。

随机数安全

如果您正确安装了 WordPress,随机数是使用您站点独有的密钥和盐生成的。NONCE_KEYNONCE_SALT在您的文件中定义wp-config.php,并且该文件包含提供更多信息的注释。

永远不应依赖随机数来进行身份验证或授权,或进行访问控制。使用 保护您的功能current_user_can(),始终假设 Nonces 可能会受到损害。

替换随机数系统

构成 nonce 系统的一些函数是可插入的,因此您可以通过提供自己的函数来替换它们。

要更改管理请求或 AJAX 请求的验证方式,您可以替换check_admin_referrer()check_ajax_referrer(),或同时替换两者。

要将 nonce 系统替换为其他一些 nonce 系统,您可以替换wp_create_nonce(),wp_verify_nonce()wp_nonce_tick()

有关的

Nonce 函数:wp_nonce_ays(), wp_nonce_field(), wp_nonce_url(), wp_verify_nonce(), wp_create_nonce(), check_admin_referer(), check_ajax_referer(),wp_referer_field()

Nonce 钩子:nonce_life, nonce_user_logged_out, explain_nonce_(verb)-(noun),check_admin_referer