WP_CREATE_NONCE在使用WP_LIST_TABLE时不进行验证

时间:2019-07-21 作者:Stef

我创建了一个管理页面,在该页面中,我使用WP\\u list\\u Table显示MySQL表的列表。在这个表中,我需要能够在需要时删除记录。这就是我的问题所在。

要删除记录,我设置了以下代码。

class Genres_List extends WP_List_Table {

    [...]

    public static function delete_genre( $id ) {
        global $wpdb;
        $wpdb->delete(
            "{$wpdb->prefix}genres",
            [ \'id\' => $id ],
            [ \'%d\' ]
            );
    }

    function column_cb( $item ) {
        return sprintf(\'<input type="checkbox" name="id[]" value="%s" />\', $item[\'id\']);
    }

    function column_name( $item ) {
        $delete_nonce = wp_create_nonce( \'sp_delete_genre\' );
        $title = \'<strong>\' . stripslashes($item[\'name\']) . \'</strong>\';
        $actions = [
            \'edit\' => sprintf( \'<a href="?page=%s&action=%s&id=%s">Bewerken</a>\', esc_attr( $_REQUEST[\'page\'] ), \'edit\', absint( $item[\'id\'] ) ),
            \'delete\' => sprintf( \'<a href="?page=%s&action=delete&id=%s&_wpnonce=%s">Verwijderen</a>\', esc_attr( $_REQUEST[\'page\'] ), absint( $item[\'id\'] ), $delete_nonce )
            ];
        return \'<a href="?page=genres&action=edit&id=\' . $item[\'id\'] . \'"><strong>\' . stripslashes($item[\'name\']) . \'</strong>\' . $this->row_actions( $actions );
    }

    function get_columns() {
        $columns = [
            \'cb\' => \'<input type="checkbox" />\',
            \'name\' => \'Naam\'
            ];

        return $columns;
    }

    public function get_bulk_actions() {
        $actions = [
            \'delete\' => \'Verwijderen\'
            ];

        return $actions;
    }

    public function process_bulk_action() {
        if ( $this->current_action() === \'delete\' ) {
            if ( ! wp_verify_nonce( $_REQUEST[\'_wpnonce\'], \'sp_delete_genre\' ) ) {
                die(\'This is a secure website. Your nonce did not verify. Go get a coffee.\');
            } else {
                self::delete_genre( absint( $_GET[\'id\'] ) );
                wp_redirect( esc_url( add_query_arg() ) );
                exit;
            }

            if ( $_POST[\'action\'] === \'delete\' || $_POST[\'action2\'] === \'delete\') {
                $delete_ids = esc_sql( $_POST[\'id\'] );

                foreach ( $delete_ids as $id ) { self::delete_genre( $id ); }

                wp_redirect( esc_url( add_query_arg() ) );
                exit;
            }
        }
    }
}
问题是wp_verify_nonce( $_REQUEST[\'_wpnonce\'], \'sp_delete_genre\' ) 尝试删除记录时返回false。我似乎找不到我做错了什么,因为我完全遵循Wordpress Codex:

使用创建noncewp_create_nonce( \'sp_delete_genre\' )._wpnonce= 参数wp_verify_nonce( $_REQUEST[\'_wpnonce\'], \'sp_delete_genre\' )

1 个回复
SO网友:JalalJaberi

这个问题很长时间没有得到回答。如果有人到这里,我会回答,以防万一。

当您使用WP_List_Table (可能是通过扩展类),为单次删除和批量删除生成的代码有所不同。单个删除通过GET 通过设置查询参数进行请求,但批量删除是通过POST 通过设置表单数据进行请求。(您可以通过检查开发人员工具的“网络”选项卡进行调查。)

因此,生成的nonce在这些情况下也有所不同,在我看来,Wordpress的设计很糟糕,两个请求都调用process_bulk_action 方法顺便说一句,您必须检查条件,例如:

if (is_array($_REQUEST[\'id\'])) {
    $true = wp_verify_nonce($_REQUEST[\'_wpnonce\'], \'bulk-\' . $this->_args[\'plural\']);
} else if (is_string($_REQUEST[\'id\'])) {
    $true = wp_verify_nonce($_REQUEST[\'_wpnonce\'], \'sp_delete_genre\');
}
您也可以检查请求方法,但我猜$_REQUEST[\'id\'] 更可靠。

P、 美国Wordpress官方网站notices 那个延伸WP_List_Table 还不够安全!

注意:此类的访问被标记为私有。这意味着它不适合插件和主题开发人员使用,因为在未来的WordPress发布中,它可能会在没有警告的情况下进行更改。如果您仍想使用该类,则应制作一份副本,以便与您自己的项目一起使用和分发,否则使用该类的风险由您自己承担。

P、 我想提一下我使用的两种资源
https://gist.github.com/petenelson/8981536
https://stackoverflow.com/questions/25000403/verifying-nonce-from-wp-list-table

相关推荐

Handling expired nonces

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