处理从访客到登录用户的操作编号

时间:2019-04-03 作者:Swen

设想以下场景:

John在我的网站上有一个帐户,但目前尚未登录在参考URL(登录后John将重定向到该URL)中,传递以下参数:action=upvote article=1234 nonce=gibberish.

WordPress有没有办法处理这样的案件?

1 个回复
最合适的回答,由SO网友:Swen 整理而成

我选择了评论中由@Rup建议的解决方案。替换两个nonce函数,wp_create_nonce()wp_verify_nonce() 为已登录和已注销的用户分别以1或0作为nonce的前缀。

注销的nonce通过IP而不是用户ID和会话令牌工作。因此,允许在登录后保留nonce。据我所知,这对安全性没有任何重大影响。

if ( ! function_exists( \'wp_create_nonce\' ) ) {
    /**
    * Creates a cryptographic token tied to a specific action, user, user session,
    * and window of time.
    *
    * @since 2.0.3
    * @since 4.0.0 Session tokens were integrated with nonce creation
    *
    * @param string|int $action Scalar value to add context to the nonce.
    * @return string The token.
    */
    function wp_create_nonce( $action = -1 ) {
        $user = wp_get_current_user();
        $uid  = (int) $user->ID;
        $logged_in = \'1-\';

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

        if ( ! $uid ) {
            // Prefix when logged-out nonce
            $logged_in = \'0-\';

            /** This filter is documented in wp-includes/pluggable.php */
            $uid = apply_filters( \'nonce_user_logged_out\', $uid, $action );

            // Use IP instead of user_id
            $uid = $_SERVER[\'REMOTE_ADDR\'];
            $token = $_SERVER[\'REMOTE_ADDR\'];
        }

        return $logged_in . substr( wp_hash( $i . \'|\' . $action . \'|\' . $uid . \'|\' . $token, \'nonce\' ), -12, 10 );
    }
}

if ( ! function_exists( \'wp_verify_nonce\' ) ) {
    /**
    * Verify that correct nonce was used with time limit.
    *
    * The user is given an amount of time to use the token, so therefore, since the
    * UID and $action remain the same, the independent variable is the time.
    *
    * @since 2.0.3
    *
    * @param string     $nonce  Nonce that was used in the form to verify
    * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
    * @return false|int False if the nonce is invalid, 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.
    */
    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 $action The nonce action.
            */
            $uid = apply_filters( \'nonce_user_logged_out\', $uid, $action );
        }

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

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

        // Check if nonce is for logged_in or logged_out (\'1-\' and \'0-\' respectively)
        if ( substr( $nonce, 0, 2 ) == \'0-\' ) {
            // Use IP instead of user_id and session token
            $uid = $_SERVER[ \'REMOTE_ADDR\' ];
            $token = $_SERVER[\'REMOTE_ADDR\'];
        }

        // Remove nonce prefix
        $nonce = substr( $nonce, 2 );

        // 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;
    }
}

相关推荐

Handling expired nonces

我有一个有几个按钮的页面。当人们单击按钮时,会发出AJAX请求并更新页面的各个部分。为了安全起见,AJAX请求使用nonce。我注意到,如果有人打开页面的时间超过了nonce过期所需的时间,那么AJAX请求将按预期停止工作。然而,我想要一个更健壮的行为。我想做的是-检测nonce何时过期/失败,然后在该点以某种方式生成一个新的nonce。这是一个由两部分组成的问题:如何检测nonce已过期</在过期的时候,最好的做法是整页刷新还是其他什么?我对安全考虑不太在行。在页面刷新之后,我想继续保持当前页面状