本文约 3,544 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:把管理员账号给客户,是灾难的开始
最常见的场景:站做好了,客户要自己发文章,于是直接把管理员账号给他。三个月后,客户装了个来路不明的”SEO 优化”插件,站点被挂黑链;或者客户在外观 → 主题文件编辑器里改了一行 PHP,前台全白。
这类事故的根因不是客户乱来,而是权限给多了。WordPress 自带的角色体系本来就能精确控制,只是大部分人没用过。
原理分析:角色与能力是两层
WordPress 权限模型分两层,容易混淆:
- 能力(Capability):最小的权限单位,是一堆字符串常量,比如
edit_posts、publish_posts、install_plugins、edit_theme_options、manage_options。 - 角色(Role):能力的一个集合,比如”作者”这个角色包含
edit_posts、publish_posts、upload_files等若干能力。
一个用户只能有一个角色(默认单站点),但可以额外附加若干能力。判断权限时永远判断能力,不判断角色:
if ( current_user_can( 'manage_options' ) ) {
// ...
}
这个细节很重要:很多插件只判断 manage_options,所以你就算建了个叫”超级编辑”的角色,只要它不含 manage_options,插件菜单照样不显示。这也是”我明明给了权限但菜单看不到”的根本原因。
五种默认角色的能力边界:
| 角色 | 写文章 | 发布文章 | 上传文件 | 编辑他人文章 | 管理评论 | 装插件/主题 | 改站点设置 |
|---|---|---|---|---|---|---|---|
| 订阅者 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| 投稿者 | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ |
| 作者 | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| 编辑 | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
| 管理员 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
多站点还多一个超级管理员(Super Admin),能管理整个网络、装主题插件、增删站点。
保姆级实操
场景一:给编辑开放插件菜单权限(不推荐但常见需求)
// 主题 functions.php 或小型功能插件
add_action( 'admin_init', function() {
$role = get_role( 'editor' );
if ( $role && ! $role->has_cap( 'manage_options' ) ) {
$role->add_cap( 'manage_options' );
}
});
警告:
manage_options等于把整个设置页交出去,包括站点地址、讨论设置、甚至部分插件的敏感配置。更安全的做法是只加install_plugins或activate_plugins,并且最好只加update_plugins。
场景二:新建一个”SEO 专员”角色
add_action( 'init', function() {
add_role( 'seo_manager', 'SEO 专员', array(
'read' => true,
'edit_posts' => true,
'edit_others_posts' => true,
'edit_published_posts' => true,
'publish_posts' => true,
'upload_files' => true,
'manage_categories' => true,
'edit_files' => false, // 明确不给主题文件编辑权
));
});
add_role() 写进数据库,只在第一次生效。改能力数组后再跑不会更新,必须先 remove_role( 'seo_manager' ) 再 add_role()。这个”改了代码没反应”的问题非常常见。
场景三:精细控制——编辑能改菜单但不能改主题
add_action( 'admin_init', function() {
$role = get_role( 'editor' );
$role->add_cap( 'edit_theme_options' ); // 能看到外观菜单
// 再把主题文件编辑器关掉
});
// 全局关闭主题/插件文件编辑器
define( 'DISALLOW_FILE_EDIT', true );
DISALLOW_FILE_EDIT 加到 wp-config.php 里,后台外观和插件菜单里就不再有”文件编辑器”。这是安全防护里性价比最高的一条,建议所有站点都加。
场景四:让作者能上传文件但看不到媒体库里别人的图
WordPress 默认媒体库对所有能 upload_files 的用户开放,看不到别人的图要额外处理:
add_filter( 'ajax_query_attachments_args', function( $query ) {
$user = wp_get_current_user();
if ( ! in_array( 'administrator', $user->roles, true )
&& ! in_array( 'editor', $user->roles, true ) ) {
$query['author'] = $user->ID;
}
return $query;
});
场景五:临时提权后回收
有时候插件要求管理员才能配置,可以给编辑临时加 manage_options,配置完再撤:
# 通过 WP-CLI 查看当前角色能力
wp role list
wp cap list editor
常见踩坑与失败案例
- 案例一:某站给编辑加了
manage_options,结果编辑在设置里把”站点地址”改错了,全站 301 到错误域名,百度快照全掉。教训:不要用manage_options当”万能钥匙”。 add_role改代码不生效:上面说过,角色存数据库,改了要删了重建。开发时建议配合wp cap add/remove命令行直接改:
bash
wp cap add editor edit_theme_options
wp cap remove editor manage_options
- 案例二:客户用管理员账号装了个”WordPress 优化”插件,插件里带了后门,站点被用来发垃圾外链。正确做法是客户只给”编辑”角色,装插件由建站方负责。
- 案例三:某多语言站给编辑加了
edit_users,结果编辑把管理员降成了订阅者,把自己锁在门外。这种只能进数据库改wp_usermeta的wp_capabilities恢复:
sql
UPDATE wp_usermeta SET meta_value = 'a:1:{s:13:"administrator";b:1;}'
WHERE user_id = 1 AND meta_key = 'wp_capabilities';
注意表前缀和 meta_key 前缀(多站点是 wp_2_capabilities)。
- 自定义文章类型的能力:注册 CPT 时如果用了
capability_type => 'post',那编辑能管;用了自定义的capability_type => 'product',则默认只有管理员有权限,编辑看不到。需要显式给角色加edit_products、publish_products等能力。
总结
权限配置的三个原则:最小权限(客户通常给”编辑”就够,投稿团队给”作者”)、永不外借管理员(要装插件就自己装)、关掉文件编辑器(DISALLOW_FILE_EDIT)。技术上记住”判断能力不判断角色”这条铁律,几乎所有”菜单不显示”的问题都能从这里找到答案。角色改动建议用 wp cap 命令行即时生效,别反复改代码重启。
