函数文档

wp_verify_nonce()

💡 云策文档标注

概述

wp_verify_nonce() 函数用于验证带有时间限制的安全 nonce,确保请求的合法性。它基于用户、操作和会话令牌生成哈希值进行比对,并返回不同状态码以指示 nonce 的有效期。

关键要点

  • 验证 nonce 的有效性,默认有效期为 12 至 24 小时。
  • 参数:$nonce(必需,待验证的 nonce 字符串),$action(可选,上下文操作,默认 -1)。
  • 返回值:1 表示 nonce 有效且生成于 0-12 小时内,2 表示有效且生成于 12-24 小时内,false 表示无效。
  • 不应依赖 nonce 进行身份验证或授权,需结合 current_user_can() 等函数进行访问控制。
  • 内部使用 wp_hash()、wp_nonce_tick() 和 wp_get_session_token() 等函数生成和验证哈希。
  • 提供 Hook:apply_filters('nonce_user_logged_out', $uid, $action) 和 do_action('wp_verify_nonce_failed', $nonce, $action, $user, $token)。

代码示例

// 示例:验证 nonce 并处理不同状态
$nonce = $_REQUEST['_wpnonce'];
$result = wp_verify_nonce($nonce, 'my-nonce');
switch ($result) {
    case 1:
        echo 'Nonce 生成于 12 小时内';
        break;
    case 2:
        echo 'Nonce 生成于 12-24 小时内';
        break;
    default:
        exit('Nonce 无效');
}

注意事项

  • nonce 验证可能受时间 tick 变化影响,导致返回值在边界时刻不精确,但通常不影响布尔检查。
  • 建议使用 isset($_REQUEST['_wpnonce']) 结合 wp_verify_nonce() 进行安全检查,避免直接依赖返回值细节。

📄 原文内容

Verifies that a correct security nonce was used with time limit.

Description

A nonce is valid for between 12 and 24 hours (by default).

Parameters

$noncestringrequired
Nonce value that was used for verification, usually via a form field.
$actionstring|intoptional
Should give context to what is taking place and be the same when nonce was created.

Default:-1

Return

int|false 1 if the nonce is valid and generated between 0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
False if the nonce is invalid.

More Information

The function is used to verify the nonce sent in the current request usually accessed by the $_REQUEST PHP variable.

Nonces should never be relied on for authentication or authorization, access control. Protect your functions using current_user_can(), always assume Nonces can be compromised.

Source

function wp_verify_nonce( $nonce, $action = -1 ) {
	$nonce = (string) $nonce;
	$user  = wp_get_current_user();
	$uid   = (int) $user->ID;
	if ( ! $uid ) {
		/**
		 * Filters whether the user who generated the nonce is logged out.
		 *
		 * @since 3.5.0
		 *
		 * @param int        $uid    ID of the nonce-owning user.
		 * @param string|int $action The nonce action, or -1 if none was provided.
		 */
		$uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
	}

	if ( empty( $nonce ) ) {
		return false;
	}

	$token = wp_get_session_token();
	$i     = wp_nonce_tick( $action );

	// Nonce generated 0-12 hours ago.
	$expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
	if ( hash_equals( $expected, $nonce ) ) {
		return 1;
	}

	// Nonce generated 12-24 hours ago.
	$expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
	if ( hash_equals( $expected, $nonce ) ) {
		return 2;
	}

	/**
	 * Fires when nonce verification fails.
	 *
	 * @since 4.4.0
	 *
	 * @param string     $nonce  The invalid nonce.
	 * @param string|int $action The nonce action.
	 * @param WP_User    $user   The current user object.
	 * @param string     $token  The user's session token.
	 */
	do_action( 'wp_verify_nonce_failed', $nonce, $action, $user, $token );

	// Invalid nonce.
	return false;
}

Hooks

apply_filters( ‘nonce_user_logged_out’, int $uid, string|int $action )

Filters whether the user who generated the nonce is logged out.

do_action( ‘wp_verify_nonce_failed’, string $nonce, string|int $action, WP_User $user, string $token )

Fires when nonce verification fails.

Changelog

Version Description
2.0.3 Introduced.

User Contributed Notes

  1. Skip to note 4 content

    Example
    Verify an nonce created with wp_create_nonce():

    " . __( 'Save Something', 'textdomain' ) . "</a>";
    ?>
    // Step B: In our file that handles the request, verify the nonce.
    $nonce = $_REQUEST['_wpnonce'];
    if ( ! wp_verify_nonce( $nonce, 'my-nonce' ) ) {
    	die( __( 'Security check', 'textdomain' ) ); 
    } else {
    	// Do stuff here.
    }

    You may also decide to take different actions based on the age of the nonce:

    $nonce = wp_verify_nonce( $nonce, 'my-nonce' );
    switch ( $nonce ) {
    	case 1:
    		echo 'Nonce is less than 12 hours old';
    		break;
    	case 2:
    		echo 'Nonce is between 12 and 24 hours old';
    		break;
    	default:
    		exit( 'Nonce is invalid' );
    }

  2. Skip to note 6 content

    This system is not very accurate and the comment about the return values is incorrect. The value 1 means < 12 hours old, but 2 means anywhere from 1 second to < 24 hours old.

    Observe what happens to the nonce tick value over a day:

    local time ~~~ seconds since epoch ~~~ tick
    2021-05-20T00:00:00+03:00 ~~~ 1621458000 ~~~ 37534
    2021-05-20T01:00:00+03:00 ~~~ 1621461600 ~~~ 37534
    2021-05-20T02:00:00+03:00 ~~~ 1621465200 ~~~ 37534
    2021-05-20T03:00:00+03:00 ~~~ 1621468800 ~~~ 37534
    2021-05-20T04:00:00+03:00 ~~~ 1621472400 ~~~ 37535
    2021-05-20T05:00:00+03:00 ~~~ 1621476000 ~~~ 37535
    2021-05-20T06:00:00+03:00 ~~~ 1621479600 ~~~ 37535
    2021-05-20T07:00:00+03:00 ~~~ 1621483200 ~~~ 37535
    2021-05-20T08:00:00+03:00 ~~~ 1621486800 ~~~ 37535
    2021-05-20T09:00:00+03:00 ~~~ 1621490400 ~~~ 37535
    2021-05-20T10:00:00+03:00 ~~~ 1621494000 ~~~ 37535
    2021-05-20T11:00:00+03:00 ~~~ 1621497600 ~~~ 37535
    2021-05-20T12:00:00+03:00 ~~~ 1621501200 ~~~ 37535
    2021-05-20T13:00:00+03:00 ~~~ 1621504800 ~~~ 37535
    2021-05-20T14:00:00+03:00 ~~~ 1621508400 ~~~ 37535
    2021-05-20T15:00:00+03:00 ~~~ 1621512000 ~~~ 37535
    2021-05-20T16:00:00+03:00 ~~~ 1621515600 ~~~ 37536
    2021-05-20T17:00:00+03:00 ~~~ 1621519200 ~~~ 37536
    2021-05-20T18:00:00+03:00 ~~~ 1621522800 ~~~ 37536
    2021-05-20T19:00:00+03:00 ~~~ 1621526400 ~~~ 37536
    2021-05-20T20:00:00+03:00 ~~~ 1621530000 ~~~ 37536
    2021-05-20T21:00:00+03:00 ~~~ 1621533600 ~~~ 37536
    2021-05-20T22:00:00+03:00 ~~~ 1621537200 ~~~ 37536
    2021-05-20T23:00:00+03:00 ~~~ 1621540800 ~~~ 37536

    …and over the boundary of a tick:

    local time ~~~ seconds since epoch ~~~ tick
    2021-05-20T14:59:58+03:00 ~~~ 1621511998 ~~~ 37535
    2021-05-20T14:59:59+03:00 ~~~ 1621511999 ~~~ 37535
    2021-05-20T15:00:00+03:00 ~~~ 1621512000 ~~~ 37535
    2021-05-20T15:00:01+03:00 ~~~ 1621512001 ~~~ 37536
    2021-05-20T15:00:02+03:00 ~~~ 1621512002 ~~~ 37536

    In this example, you can see that a nonce generated at 3pm and verified one second later will return 2 because of the tick change. The ticks do not align with timezones due to their basis in universal time, so nonces will always appear “old” to your code at certain times of the day.