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
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. |
Skip to note 4 content
Codex
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' ); }Skip to note 5 content
WordProof
Per the WordPress Coding Standards, this is the way as to verify a nonce:
if ( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'wpdocs-my-nonce' ) ) { //do you action } else { die( __( 'Security check', 'textdomain' ) ); }Skip to note 6 content
Roy Orbitson
This system is not very accurate and the comment about the return values is incorrect. The value
1means < 12 hours old, but2means 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
2because 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.