跳到主内容

WordPress 用户角色与权限怎么划分:角色、能力(Capabilities)与自定义角色实战

100%
WordPress 用户角色与权限怎么划分:角色、能力(Capabilities)与自定义角色实战

一句话答案:WordPress 的权限体系不是「角色」在起作用,而是「能力(Capability)」在起作用——角色只是能力的一个打包套餐。正确的做法是给用户分配角色、在代码里只判断能力(current_user_can()),需要细分时再自定义角色或用 add_cap() / remove_cap() 增删单项能力。

很多人把 WordPress 的权限理解成「管理员 / 编辑 / 作者」这几档固定选项,于是遇到「让编辑能改菜单但不能装插件」这种需求就卡住,要么直接给管理员,要么装一堆权限插件。实际上 WordPress 自带的角色与能力机制足够覆盖绝大多数场景,代价只是你要理解三个概念:角色、能力、元能力。

角色和能力的关系:一个是套餐,一个是单项

官方文档的定义很明确:WordPress 把角色和能力存在 wp_options 表的 user_roles 键里;角色定义了一组能力的集合,能力才真正决定用户能看什么、做什么。默认有六个角色:

角色slug典型能力适用人群
超级管理员(仅多站点)站点网络全部能力网络所有者
管理员administrator单站内全部管理功能站点负责人
编辑editor发布并管理文章,含他人文章内容主编
作者author发布并管理自己的文章专栏作者
贡献者contributor撰写和管理自己的文章,不能发布投稿人
订阅者subscriber仅 read,管理个人资料注册用户

关键点:角色之间没有「高级 / 低级」之分,它们只是职责划分。订阅者只有 read,不是因为它「级别低」,而是因为它只负责读。

自定义角色:add_role() 有一个必须知道的幂等陷阱

新增角色用 add_role(),它接收角色 slug 、显示名和能力数组:

function wporg_simple_role() {
    add_role(
        'simple_role',
        '简单角色',
        array(
            'read'         => true,
            'edit_posts'   => true,
            'upload_files' => true,
        )
    );
}
add_action( 'init', 'wporg_simple_role' );

坑在这里:第一次调用 add_role() 之后,角色和能力就写进数据库了,后续调用什么都不会发生——包括你后来改了能力数组。这就是为什么很多人改了代码却发现后台权限没变。

要批量改能力,正确姿势是先 remove_role() 再 add_role(),并且必须加条件判断,否则每次请求都读写数据库,性能会明显下降:

function wporg_sync_role() {
    $role = get_role( 'simple_role' );
    if ( $role && ! $role->has_cap( 'edit_others_posts' ) ) {
        remove_role( 'simple_role' );
        add_role( 'simple_role', '简单角色', array(
            'read'               => true,
            'edit_posts'         => true,
            'edit_others_posts'  => true,
            'upload_files'       => true,
        ) );
    }
}
add_action( 'init', 'wporg_sync_role' );
不要删除 administrator 和 super admin 角色。如果确实要移除 subscriber(它是 WordPress 的默认角色),记得同步执行 update_option(‘default_role’, ‘你的新默认角色’),否则新用户注册会落到不存在的角色上。

只想微调?用 add_cap() / remove_cap()

如果只是在现有角色上加减一两项能力,不必重建角色:拿到角色对象再操作即可,挂钩优先级要排在角色定义之后。

function wporg_add_caps() {
    $role = get_role( 'editor' );
    if ( $role ) {
        $role->add_cap( 'edit_theme_options' );
        $role->remove_cap( 'manage_categories' );
    }
}
add_action( 'init', 'wporg_add_caps', 11 );

代码里判断权限:只查能力,别查角色

判断权限有两个常用函数:

  • current_user_can( $cap, ...$args ) —— 判断当前用户
  • user_can( $user, $cap, ...$args ) —— 判断指定用户,第三个参数可传对象 ID 做针对性校验

官方文档明确提示:用角色名代替能力去做判断虽然「部分可用」,但结果不可靠,属于不推荐做法。原因很直白——角色可以被插件改,能力才是最终裁决依据。

元能力:为什么 edit_post 要传文章 ID

能力分两类。edit_posts 这类是「原始能力」,角色直接拥有;edit_post、edit_user、edit_post_meta 这类是「元能力」,会通过 map_meta_cap() 映射成原始能力再校验。

current_user_can( 'edit_posts' );              // 原始能力,直接查
current_user_can( 'edit_post', $post->ID );    // 元能力,需带对象 ID
current_user_can( 'edit_post_meta', $post->ID, $meta_key );

同一个 edit_post,作者写自己的文章映射成 edit_posts,编辑改别人的文章映射成 edit_others_posts。不传 ID 就无从判断,这也是权限代码最常见的 bug 来源。

为什么超级管理员永远返回 true?
current_user_can() 对超级管理员一律返回 true,除非显式 deny 。写权限分支测试时要单独造普通管理员账号,否则测试永远通过、上线就出问题。多站点场景用 current_user_can_for_blog( $blog_id, $cap ) 指定站点。

实战:搭一个「内容运营」角色


  1. 明确职责边界:能写能发能传图、能改菜单和站点设置,不能装插件换主题、不能动用户。

  2. 用 add_role() 建 content_operator 角色,能力给 read 、 edit_posts 、 edit_others_posts 、 publish_posts 、 edit_published_posts 、 upload_files 、 manage_categories 、 edit_theme_options 。

  3. 在主题和插件的敏感入口统一用 current_user_can( ‘activate_plugins’ ) 之类的能力判断,不写角色名。

  4. 用 user_can( $user_id, ‘edit_post’, $post_id ) 写一段校验脚本,抽查该角色对他人文章的编辑权限是否真的生效。

  5. 后台手动把测试账号切到该角色,逐项点一遍后台菜单,确认没有残留入口。

注意 edit_theme_options 的「外溢效应」:它不只解锁站点编辑器,还会解锁外观 > 小工具、外观 > 菜单、外观 > 自定义、外观 > 头部。给这个能力等于送出一串后台入口,务必确认这是你想要的。

REST API 时代的权限排查:401 和 403 怎么看

区块编辑器、站点编辑器都是走 REST API 读写的,权限问题会以接口报错的形式暴露出来:

  • 模板、模板部件、导航等端点校验 edit_theme_options
  • 文章、页面类端点校验 edit_posts、edit_pages、edit_others_posts
  • 缺失时返回 401 Unauthorized 或 403 Forbidden,响应体里通常带具体失败的能力名

典型症状:自定义角色能打开站点编辑器,但某些区块保存失败。排查方法就是打开浏览器开发者工具,看哪个请求返回 401/403,再对照响应里的错误码补对应能力。这一步比猜要快得多。

unfiltered_html 的特殊规则

unfiltered_html 允许用户在文章、页面、评论、小工具里写入未过滤的 HTML 甚至 JavaScript 。官方明确警告:给不可信用户开这个能力等于开后门。在 WordPress 多站点下,只有超级管理员拥有 unfiltered_html,单站点管理员默认拥有。

权限设计的三条实践建议

  1. 最小权限原则:只给完成职责必需的能力。一次多给,后面很难收回。
  2. 能力优先于角色:所有代码判断写 current_user_can(),角色只用于后台分配。
  3. 自定义能力要有命名空间:比如 jinyu_manage_billing,避免和核心或插件能力撞名。自定义能力在默认后台不产生任何效果,但可以在自定义后台页面和前台逻辑里用——这正是它的价值。

权限这件事,做对的标志不是「功能都能用」,而是「不该出现的东西一个都没出现」。角色只是入口,能力才是闸门。


改了 add_role() 的能力数组,为什么后台没变化?
因为 add_role() 只在角色首次创建时写入数据库,之后调用不会更新已有角色。想批量改能力必须先 remove_role() 再 add_role(),并加条件判断避免每次请求都写库;只是增删单项能力用 get_role()->add_cap() / remove_cap() 更稳。

current_user_can('edit_post') 为什么判断不准?
edit_post 是元能力,必须通过 map_meta_cap() 映射成 edit_posts 或 edit_others_posts,而映射需要知道具体是哪篇文章。正确写法是 current_user_can( ‘edit_post’, $post->ID ),不传对象 ID 就无法判断。

可以给某个用户单独加能力吗?
可以。 WP_User 对象同样提供 add_cap() 和 remove_cap(),用户级能力会和角色能力合并生效,也可以单独 deny 掉角色原本拥有的某项能力。这种「按人例外」适合临时授权,不建议作为长期方案。

自定义角色打开站点编辑器后部分功能报错怎么办?
站点编辑器走 REST API,模板与模板部件端点校验 edit_theme_options,文章页端点校验 edit_posts / edit_pages / edit_others_posts 。用浏览器开发者工具找到返回 401 或 403 的请求,响应体里的错误码会指明缺少哪项能力,补齐即可。

相关阅读

这篇有帮助吗?
云上的幻象
云上的幻象查看主页

七彩云博客,分享 WordPress 建站实战与 AI 工具测评,覆盖服务器运维、站长工具、软件资源与电商运营干货,专注原创实用的主题插件、网站加速与安全优化教程。

997文章4评论

相关文章

评论 (0)

欢迎你,新朋友,感谢参与互动!文明发言,理性交流 · 首次评论将在审核后展示