如果您的插件允许用户提交数据——无论是在后台还是前台——它都应该检查用户权限。

用户角色与权限

创建高效安全层的最重要步骤是建立用户权限系统。WordPress 通过用户角色与权限(User Roles and Capabilities)提供这一功能。

每个登录 WordPress 的用户都会根据其用户角色自动分配特定的用户权限。

用户角色(User roles)只是指用户所属组的另一种说法。每个组都有一组特定的预定义权限。

例如,您网站的主要用户将拥有“管理员(Administrator)”用户角色,而其他用户可能拥有“编辑(Editor)”或“作者(Author)”等角色。您可以将多个用户分配给同一个角色,即一个网站可能有两位管理员。

用户权限(User capabilities)是您分配给每个用户或用户角色的特定权限。

例如,管理员拥有"manage_options"权限,这使他们能够查看、编辑和保存网站的选项。而编辑则缺乏此权限,这将阻止他们与选项进行交互。

这些权限随后会在后台的各个位置进行检查。根据分配给角色的权限;WordPress 体验中的菜单、功能和其他方面可能会被添加或移除。

在构建插件时,请确保仅在当前用户具备必要权限时才运行您的代码。

层级结构

用户角色越高,其拥有的权限就越多。每个用户角色都会继承层级结构中之前角色的权限。

例如,“管理员(Administrator)”是单个站点安装中的最高用户角色,它继承以下角色及其权限:“订阅者(Subscriber)”、“投稿人(Contributor)”、“作者(Author)”和“编辑(Editor)”。

示例

无限制

下面的示例在前端创建一个链接,赋予删除帖子的能力。由于此代码未检查用户权限,它允许任何访问该站点的访客删除帖子!

/**
 * Generate a Delete link based on the homepage url.
 *
 * @param string $content   Existing content.
 *
 * @return string|null
 */
function wporg_generate_delete_link( $content ) {
	// Run only for single post page.
	if ( is_single() && in_the_loop() && is_main_query() ) {
		// Add query arguments: action, post.
		$url = add_query_arg(
			[
				'action' => 'wporg_frontend_delete',
				'post'   => get_the_ID(),
			], home_url()
		);

		return $content . ' <a href="' . esc_url( $url ) . '">' . esc_html__( 'Delete Post', 'wporg' ) . '</a>';
	}

	return null;
}

/**
 * Request handler
 */
function wporg_delete_post() {
	if ( isset( $_GET['action'] ) && 'wporg_frontend_delete' === $_GET['action'] ) {

		// Verify we have a post id.
		$post_id = ( isset( $_GET['post'] ) ) ? ( $_GET['post'] ) : ( null );

		// Verify there is a post with such a number.
		$post = get_post( (int) $post_id );
		if ( empty( $post ) ) {
			return;
		}

		// Delete the post.
		wp_trash_post( $post_id );

		// Redirect to admin page.
		$redirect = admin_url( 'edit.php' );
		wp_safe_redirect( $redirect );

		// We are done.
		die;
	}
}

/**
 * Add the delete link to the end of the post content.
 */
add_filter( 'the_content', 'wporg_generate_delete_link' );

/**
 * Register our request handler with the init hook.
 */
add_action( 'init', 'wporg_delete_post' );

限制为特定权限

上面的示例允许任何访问该站点的访客点击“删除”链接并删除帖子。然而,我们只希望“编辑”及以上级别的访客能够点击“删除”链接。

为了实现这一点,我们将检查当前用户是否拥有edit_others_posts权限,只有“编辑”及以上级别的用户才拥有此权限:

/**
 * Generate a Delete link based on the homepage url.
 *
 * @param string $content   Existing content.
 *
 * @return string|null
 */
function wporg_generate_delete_link( $content ) {
	// Run only for single post page.
	if ( is_single() && in_the_loop() && is_main_query() ) {
		// Add query arguments: action, post.
		$url = add_query_arg(
			[
				'action' => 'wporg_frontend_delete',
				'post'   => get_the_ID(),
			], home_url()
		);

		return $content . ' <a href="' . esc_url( $url ) . '">' . esc_html__( 'Delete Post', 'wporg' ) . '</a>';
	}

	return null;
}

/**
 * Request handler
 */
function wporg_delete_post() {
	if ( isset( $_GET['action'] ) && 'wporg_frontend_delete' === $_GET['action'] ) {

		// Verify we have a post id.
		$post_id = ( isset( $_GET['post'] ) ) ? ( $_GET['post'] ) : ( null );

		// Verify there is a post with such a number.
		$post = get_post( (int) $post_id );
		if ( empty( $post ) ) {
			return;
		}

		// Delete the post.
		wp_trash_post( $post_id );

		// Redirect to admin page.
		$redirect = admin_url( 'edit.php' );
		wp_safe_redirect( $redirect );

		// We are done.
		die;
	}
}

/**
 * Add delete post ability
 */
add_action('plugins_loaded', 'wporg_add_delete_post_ability');
 
function wporg_add_delete_post_ability() {    
    if ( current_user_can( 'edit_others_posts' ) ) {
        /**
         * Add the delete link to the end of the post content.
         */
        add_filter( 'the_content', 'wporg_generate_delete_link' );
      
        /**
         * Register our request handler with the init hook.
         */
        add_action( 'init', 'wporg_delete_post' );
    }
}