如果您的插件允许用户提交数据——无论是在管理端还是公共端——它都应该检查用户权限。
用户角色和权限
创建高效安全层的最重要步骤是建立用户权限系统。WordPress 以 用户角色和权限 的形式提供此功能。
每个登录到 WordPress 的用户都会根据其用户角色自动分配特定的用户权限。
用户角色 只是指用户所属的组的一种说法。每个组都有一组特定的预定义权限。
例如,您网站的主要用户将拥有管理员用户角色,而其他用户可能拥有编辑者或作者等角色。您可以为某个角色分配多个用户,即一个网站可能有两名管理员。
用户权限 是您分配给每个用户或用户角色的特定权限。
例如,管理员拥有“manage_options”权限,允许他们查看、编辑和保存网站的选项。另一方面,编辑者缺乏此权限,这将阻止他们与选项进行交互。
这些权限会在管理端的各个点进行检查。根据分配给某个角色的权限;可能会添加或删除 WordPress 体验中的菜单、功能和其他方面。
在构建插件时,请确保仅在当前用户具有必要权限时才运行您的代码。
层级
用户角色越高,用户拥有的权限就越多。每个用户角色都会继承层级中的前一个角色的权限。
例如,“管理员”是单站点安装中最高级别的用户角色,它继承了以下角色及其权限:“订阅者”、“贡献者”、“作者”和“编辑者”。
示例
无限制
下面的示例在前端创建一个链接,允许删除帖子。由于此代码未检查用户权限,它允许任何访问者删除帖子!
/**
* 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' );
}
}