Wordpress

WordPress 使用者角色權限怎麼管理?內建角色差異與自訂技巧一次掌握

多數人以為,管理員、編輯、作者這幾個角色的差別只是介面上能看到的選單不一樣,其實 WordPress 判斷一個使用者能不能做某件事,靠的是逐一比對一串能力字串,角色只是把一批能力包起來、方便套用的容器而已。這也是為什麼很多網站在開放多人協作之後,會遇到「這個角色好像什麼都能做,那個角色卻連上傳一張圖片都不行」的困擾,不是角色選錯了,是預設的五種角色從一開始就沒打算涵蓋所有分工情境。

使用者角色權限(user roles and permissions)在 WordPress 裡其實拆成兩層,角色(role)決定一個帳號屬於哪一群,能力(capability)才是真正決定能不能做這件事的最小單位。搞懂這兩層的關係,才看得懂為什麼系統管理員能刪外掛、編輯卻連自己的佈景主題設定都碰不到,也才有辦法在預設角色不夠用的時候,動手建一個剛好符合團隊分工的新角色,而不是在該給誰管理員權限這個問題上一直將就。

WordPress 靠能力字串決定使用者可以做的事

系統管理員、編輯、作者這些名稱,只是 WordPress 給一批能力取的方便稱呼,真正決定一個使用者能不能編輯某篇文章、能不能安裝外掛的,是一長串像edit_posts、publish_posts、install_plugins這樣的能力字串。角色只是把常用的能力組合打包起來,方便一次套用給一整群人,並不是 WordPress 內部真正用來判斷權限的單位。

WordPress 核心用來檢查這件事的函式是current_user_can(),它會拿目前登入的使用者去比對某個能力字串,回傳能或不能。像wp-admin/includes/post.php這類核心檔案,在讓使用者編輯一篇文章之前,並不是先看這個人是不是編輯,而是直接呼叫current_user_can( 'edit_post', $post_id )這個檢查,沒有這個能力,請求會直接被擋下,畫面上出現的是一句沒有權限進行此操作的提示,不會一路帶著角色名稱去做例外處理。

if ( current_user_can( 'edit_post', $post_id ) ) {
    // 使用者具備編輯這篇文章的能力,才進入編輯流程
}Code language: PHP (php)

角色與能力的完整清單,實際上以序列化陣列的形式存在資料庫的wp_options資料表裡,選項名稱固定叫wp_user_roles(單站安裝的情況下,若資料表前綴有變動,名稱會跟著wp-config.php裡設定的$table_prefix一起變動)。每個使用者身上掛的角色,則記錄在wp_usermeta的wp_capabilities這個 meta 欄位裡,這筆資料本身只存著他屬於哪個角色(以及額外對這個使用者個別加上去的能力),角色實際包含哪些能力字串,要對照wp_user_roles裡那個角色的定義才查得到。

除了角色內建的能力之外,WordPress 也允許只針對某一位使用者額外加能力,不用動到整個角色。做法是先取得該使用者的WP_User物件,再呼叫add_cap():

$user = new WP_User( $user_id );
$user->add_cap( 'manage_options' );Code language: PHP (php)

一個使用者實際擁有的能力,等於他所屬角色原本的那包能力,加上個別疊加上去的能力。兩個掛著同一個角色的帳號,實際能做的事仍然可能不一樣,判斷一個人能不能做某件事,永遠要看他當下真正擁有的能力組合,而不是只看角色名稱。

角色只是把能力打包起來的容器,帳號實際能做的事等於角色能力加上 add_cap 個別疊加的能力,WordPress 靠 current_user_can 比對能力字串而非角色名稱
WordPress 判斷權限看的不是角色名稱,而是這個帳號當下真正擁有的那組能力字串。

五種內建角色,權限邊界一次攤開

WordPress 內建五種角色,由高到低分別是系統管理員、編輯、作者、投稿者、訂閱者,能力等級是疊加的,上層角色通常涵蓋下層角色的能力,這是設計上刻意的邏輯,不是巧合。read是唯一五種角色都有的能力,代表能不能登入後台看到東西是最基本的門檻,再往上才依序疊加編輯、發佈、管理其他人內容、管理全站設定的能力。這也是為什麼很多網站在權限出問題時,抱怨的常常不是某個角色沒有能力,而是某個角色多了不該有的能力,邊界劃在哪裡,遠比角色叫什麼名字重要。

WordPress 五種內建角色從訂閱者到系統管理員能力逐層疊加,上層通常涵蓋下層,read 是五種角色唯一共有的能力
五種內建角色的能力由低到高疊加,每往上一階就多拿到一批能力,read 則是所有角色共有的最基本門檻。

系統管理員能改外掛、佈景主題的核心設定

系統管理員擁有的能力,是其餘四種角色完全沒有、也不該有的那一塊:安裝與刪除外掛、安裝與刪除佈景主題、直接編輯核心檔案、新增與刪除使用者、更新 WordPress 核心版本。官方能力對照表列出的這批能力字串包括install_plugins、delete_plugins、edit_plugins、install_themes、delete_themes、edit_themes、edit_files、edit_users、add_users、create_users、delete_users、update_core、unfiltered_html,單站安裝下只有系統管理員才有。

這批能力一旦被賦予,幾乎等於能完全接管一個網站,裝一支外掛就能執行任意程式碼,改一段核心檔案就能繞過任何前端限制。這也帶出後面章節會反覆提到的判斷原則,與其把某個協作者硬套進系統管理員角色圖方便,不如先看清楚他真正需要哪幾項能力,再決定要不要自訂一個更貼身的角色。

編輯能發佈也能修改所有人的文章

編輯的核心邊界,劃在誰的內容這條線上。編輯可以編輯、發佈、刪除任何人的文章與頁面,也能管理留言、分類與連結,官方對照表列出edit_others_posts、edit_pages、edit_others_pages、publish_pages、delete_pages、delete_others_pages、moderate_comments、manage_categories、manage_links這一整批能力,都是編輯才有、作者以下沒有的部分。

但編輯完全碰不到外掛、佈景主題、使用者管理這幾塊,沒有任何相關能力。這個角色適合放給內容把關者,像是總編輯、內容主管,讓他能審核與調整所有人寫的東西,但不該把編輯當成半個管理員來用,只是需要有人幫忙管理留言或審稿,不代表對方也該連佈景主題外觀一起管。

作者只能發佈、刪除自己的文章

作者能寫、能發佈、也能上傳媒體檔案,官方能力對照表裡,作者比投稿者多出publish_posts、edit_published_posts、delete_published_posts、upload_files這 4 項,是投稿者沒有、卻不到編輯那麼多的一段能力(edit_posts、delete_posts則是作者與投稿者都有的基本能力,差別在投稿者只能對還沒發佈的自己文章動用)。作者能把自己寫的文章從頭到尾走完一輪流程,不必假手他人按下發佈鍵。

但只要牽涉到別人的文章或建立分類,作者就沒有權限,沒有edit_others_posts,也沒有manage_categories,更沒有建立頁面的能力。有個細節容易被忽略,作者刪除自己已發佈文章的能力,是預設就有的,不是額外加上去的。這代表團隊裡的作者若一時手滑,可以直接把自己已經上線的文章整篇刪掉,不需要額外授權,也不會跳出任何確認關卡,如果這不是你想要的行為,可以用remove_cap()把delete_published_posts從作者角色拿掉。

投稿者寫得出文章,發佈鍵卻按不下去

投稿者是五種角色裡最容易被誤解的一種。投稿者能寫文章、能編輯自己還沒發佈的草稿、也能刪除自己那些還沒發佈的草稿,官方對照表顯示edit_posts、delete_posts這兩項能力投稿者都有,但條件限定在未發佈狀態、且是自己的文章。

投稿者完全沒有publish_posts,連自己寫的文章都要交給編輯或系統管理員按下發佈鍵才會上線。也沒有upload_files,不能上傳媒體檔案,這一點常讓新手感到意外,寫到一半想插一張圖,才發現媒體庫的上傳按鈕根本不會出現。實務上,投稿者這個角色適合外部投稿人、還在試用期的新手作者,讓內容經過至少一次審核才公開,但也要記得先幫他準備好圖片素材,或者請有上傳能力的人代為處理,不然稿子寫到一半會因為沒辦法自己上傳圖片而中斷。

訂閱者的權限就只夠管理個人資料

訂閱者只有read這一項能力,官方對照表裡沒有其他任何一項打勾。這代表訂閱者可以登入 WordPress 後台,但幾乎看不到任何管理選單,能做的事僅限於編輯自己的個人資料、密碼這類基本設定。

實務上,訂閱者這個角色很少用在內容協作,多半用在需要登入才能看到某些內容的情境,像是會員專屬文章、需要註冊才能下載的資源、或是付費牆前的免費會員層級。訂閱者只有一種身分,分不出已經付費跟還沒付費,會員或線上課程網站一旦需要依付費層級開放不同內容,單靠這五種預設角色就會不夠用。

五種角色卡不住的協作與會員需求

把五種角色的邊界攤開之後,能看出一個共通點,預設角色是按著寫部落格的邏輯設計的,一個人寫文章、一個人審核、一個人管全站,分工模式很單純。但團隊分工或會員網站的實際需求,經常跟這套發文流程對不上,落差就會冒出來。

情境一是只需要管理留言與特定分類文章的社群小編。要讓對方能審核留言、排文章上線,最貼近的預設角色是編輯,但編輯這個角色連分類建立、佈景主題外觀都一起打包給了出去,對方原本只被交辦管留言、發文,卻連帶拿到了他不需要、也不該有的能力。

情境二是會員或線上課程網站,依付費層級開放不同內容。前一節提過,訂閱者只有一種身分,分不出已付費和未付費,五種預設角色裡也沒有第二種登入但沒付費的身分可以套。

情境三是外部協作者、實習生或代理商,他們通常只該碰到被交辦的那一小塊工作,例如只改某幾頁的文案,或只處理某個分類底下的文章。套用最小權限原則(principle of least privilege),也就是每個帳號只給工作所需的最低能力,比硬套一個有落差的預設角色更安全,多出來的能力永遠都是風險,不是備而不用的方便。

這三個情境背後其實是同一件事,使用者角色權限不該用哪個預設角色最接近來決定,而該回頭問這個帳號實際需要做什麼。知名外掛實際擴充角色的做法,可以佐證預設角色真的不夠用這件事並不是少數個案。WooCommerce 安裝之後,會額外新增 Customer 與 Shop Manager 兩種角色:Customer 近似訂閱者,但多了查看自己訂單與帳號資料的能力;Shop Manager 近似編輯,再加上商品與訂單管理的能力。這正是官方生態系對五種角色不夠用給出的解法示範,與其把商店管理員硬套進編輯或系統管理員,不如照著需求另外開一個角色。

用 add_role 建立一個全新的角色

預設角色的邊界攤開、落差也看清楚之後,可以進到實作。add_role()是 WordPress 用來從零建立一個角色的函式,讓你不必再把人硬塞進最接近的預設角色,而是直接指定這個角色該有哪些能力。

add_role( $role, $display_name, $capabilities )這個函式吃三個參數,$role是角色的英文代稱,像site_editor這種給程式用的 slug,$display_name是後台選單上顯示的名稱,$capabilities則是一個關聯陣列,鍵是能力字串、值是true或false,決定這個新角色一開始要打包哪些能力。

add_role(
    'simple_role',
    'Simple Role',
    array(
        'read'         => true,
        'edit_posts'   => true,
        'upload_files' => true,
    )
);Code language: PHP (php)

這支範例建立一個叫simple_role的角色,給它read、edit_posts、upload_files三項能力,能登入後台、能寫文章、也能上傳媒體檔案,但沒有發佈、沒有管理別人內容的能力。

第一個容易踩的雷,是add_role()第一次呼叫之後,角色與能力就會寫進資料庫,之後每次頁面載入都重複呼叫這支函式,並不會更新已經存在的角色,包括你之後想調整能力清單,也不會生效。要改一個已經建立好的角色,得先呼叫remove_role()把舊角色移除,再重新呼叫add_role()建一次,而且動手之前要先判斷能力清單是不是真的變了才這麼做,不然每次頁面載入都刪掉重建,會明顯拖慢網站速度。

第二個容易踩的雷,是這段程式碼該放在哪裡。建議放進一支輕量的自訂外掛,或是mu-plugins資料夾,而不是放進佈景主題的functions.php。原因是換佈景主題不會自動移除已經寫進資料庫的角色,但如果這個角色當初是靠functions.php裡的程式碼才建立出來的,換主題之後那段程式碼就跟著消失,之後想再調整或移除這個角色,反而找不到源頭在哪裡。

function custom_register_assistant_role() {
    add_role(
        'assistant',
        'Assistant',
        array(
            'read'             => true,
            'activate_plugins' => true,
            'update_plugins'   => true,
        )
    );
}
register_activation_hook( __FILE__, 'custom_register_assistant_role' );

function custom_remove_assistant_role() {
    remove_role( 'assistant' );
}
register_deactivation_hook( __FILE__, 'custom_remove_assistant_role' );Code language: PHP (php)

這支範例示範一個只能安裝與更新外掛的assistant角色,能力給read、activate_plugins、update_plugins,搭配register_activation_hook()與register_deactivation_hook(),讓這個角色隨外掛啟用而自動建立,隨外掛停用而自動移除,不用手動去後台操作。

用 add_cap 和 remove_cap 調整既有角色的能力

不是每次調整權限都需要新增一個角色,多數時候,只是想在某個既有角色上多給一點、或少給一點能力,這時候用add_cap()和remove_cap()比重新建一個角色更直接。

要調整既有角色,得先透過get_role( $role_slug )拿到對應的WP_Role物件,再呼叫這個物件的add_cap()或remove_cap(),不能直接對著角色名稱這個字串呼叫。跟建立新角色一樣,這是永久寫進資料庫的異動,應該掛在外掛啟用鉤子上只執行一次,不要讓它在每次頁面載入時都重跑一遍。

$role = get_role( 'editor' );
$role->add_cap( 'activate_plugins' );
$role->add_cap( 'update_plugins' );Code language: PHP (php)

這段範例讓編輯這個角色多出安裝與更新外掛的能力,原本編輯完全碰不到外掛管理,加上這兩項之後,就能在不動用系統管理員帳號的情況下,幫忙處理外掛更新這類例行維護工作。

$role = get_role( 'author' );
$role->remove_cap( 'delete_published_posts' );Code language: PHP (php)

反過來,這段範例把作者角色的delete_published_posts拿掉,對應的正是前面提過的那個細節,作者刪除自己已發佈文章的能力預設就有,一時衝動整篇刪掉的風險也跟著存在。拿掉這項能力之後,作者仍然可以刪除自己還沒發佈的草稿,但已經公開上線的內容,就只能改成草稿或送審,不能直接一鍵刪除,對整個網站的內容安全來說,是個很划算的一次性調整。

不寫程式,用角色管理外掛完成同樣的事

角色管理外掛把整套操作變成後台介面裡的勾選動作,在畫面上勾選核取方塊,就能完成新增、複製、調整角色的工作,不必寫任何一行程式碼。

這類外掛的邏輯大同小異,列出 WordPress 目前所有的能力供你逐項勾選、可以直接複製一個既有角色再修改而不必從零開始、可以把多個角色同時指派給同一個使用者、也能把已經停用的外掛殘留下來卻沒被清乾淨的能力手動移除。

User Role Editor 是 WordPress.org 官方外掛目錄裡長年維護、免費版功能就已經完整的一款代表。操作方式是勾選想要的能力之後按下更新即可儲存,也能從零建立角色或複製既有角色再修改,能力可以單獨指派給某一位使用者,同一個使用者也能同時掛多個角色,並支援多站安裝的環境。

Members 則是另一款同類型外掛,除了角色與能力的編輯功能之外,還多了依角色或能力限制文章、頁面、區塊可見範圍的內容權限功能。它內建一個叫做 Administrator Rescue 的救援機制,萬一調整角色時不小心把自己鎖在管理員權限之外,可以透過電子信箱收到一組限時連結,直接恢復管理員身分,不需要動資料庫,也不用找主機商協助救援。

新角色沒先測試,很容易把自己也鎖在外面

不管是用程式碼還是外掛調整角色,改完程式碼或按下更新按鈕之後,直接把新角色指派給真實使用者,是最容易出事的做法。上線前應該先驗證這個角色實際能做什麼、不能做什麼。

官方建議的測試流程其實不複雜,先建立一個測試帳號,指派新角色給它,再登入這個測試帳號逐項確認該有的能力有沒有出現、不該有的能力有沒有被擋下,接著直接嘗試存取更高層級的後台頁面,確認真的被拒絕而不是矇混過關,驗證無誤之後再刪除這個測試帳號。這個流程花不了多少時間,卻能提早抓到這個角色其實比原本以為的多給了一些能力這種容易被忽略的落差。

調整或移除角色能力時,有個常見的自傷案例值得留意。如果不小心動到自己目前這個帳號所屬角色的manage_options、edit_users、remove_users這類能力,很可能會把自己鎖在管理功能之外,連回頭補救都進不了後台。前面提到的 Members 外掛內建救援連結,某種程度上就是為了應付這種情況而存在。

另一個容易忽略的細節是,刪除使用者的時候,WordPress 會要求選擇把該使用者名下的內容改指派給哪一個帳號,不做這個選擇,那個使用者的文章、頁面這些內容就會跟著被一併刪除。角色被移除或使用者被刪除之後,內容歸屬不會自動消失,但也不會自動找到新主人,需要當下手動處理。套用最小權限原則、定期覆核既有角色與使用者名單,是官方建議會持續帶來效益的例行安全動作。

區塊佈景主題的版面編輯,一樣要靠能力開放

區塊佈景主題(block theme)啟用之後,後台會多出一個網站編輯器(Site Editor),讓使用者直接在裡面調整版面、樣式、導覽選單,這個入口同樣是靠能力系統決定誰能進去,並不是另外拉出一套獨立的權限機制。

判斷一個使用者能不能進入網站編輯器與它底下的選單,主要看edit_theme_options這項能力。單站安裝下,預設只有系統管理員擁有這項能力,編輯以下的角色都沒有,這代表就算是負責內容的編輯,也不能單靠現有角色去動版面設定。

只有edit_theme_options還不夠讓一個角色真的在網站編輯器裡把事情做完。管理範本要用到edit_posts,管理頁面範本要用到edit_pages,範本常常牽涉到別人建立的內容,所以還需要edit_others_posts,上傳圖片素材要靠upload_files,預覽變更則要靠所有角色都有的read。

add_role(
    'site_editor',
    'Site Editor',
    array(
        'read'               => true,
        'edit_theme_options' => true,
        'edit_posts'         => true,
        'edit_pages'         => true,
        'edit_others_posts'  => true,
        'upload_files'       => true,
    )
);Code language: PHP (php)

這支範例建立一個叫site_editor的角色,把上面幾項能力組合在一起,讓這個角色能實際操作網站編輯器、調整版面與範本,卻完全沒有外掛、使用者管理這類能力。跟前面示範建立assistant、simple_role這類自訂角色的做法是同一套邏輯,只是這次組合能力的目的,是為了因應版面編輯這個新的情境。

下一次面對這個協作者該給他什麼權限這個問題,值得先停下來想一次,他實際需要做的事,是不是剛好卡在某個預設角色的邊界上。使用者角色權限這件事,決定的不只是後台選單長什麼樣子,也決定了一旦帳號外洩或協作者操作出錯,傷害能被限制在多小的範圍裡。花幾分鐘用remove_cap()拿掉一項不需要的能力,或是用測試帳號把新角色跑過一輪,通常比事後補救省下的時間多得多。

常見問答

本區問答由 AI 依文章內容自動整理,僅供快速參考,正式內容仍以全文為準。

WordPress 靠什麼判斷使用者能不能做某件事?

靠一長串能力字串,不是角色名稱。核心函式 current_user_can() 會比對使用者有沒有某項能力,例如編輯文章前檢查有沒有 edit_post,沒有就直接擋下請求;角色只是把常用能力包起來、方便套用給一整群人的容器。

WordPress 內建的訂閱者角色能做哪些事?

訂閱者只有 read 這一項能力,能登入後台但幾乎看不到任何管理選單,能做的事僅限編輯自己的個人資料與密碼;實務上很少用在內容協作,多半用在需要登入才能看到會員專屬文章或付費牆前免費內容的情境。

作者能不能刪除自己已發佈的文章?

可以,這項能力預設就有、不是額外加上去的,代表作者一時手滑也能把已上線文章整篇刪掉,不需要額外授權也不會跳出確認關卡;不想要這個行為,可以用 remove_cap() 把該能力從作者角色拿掉。

自訂角色的 add_role() 程式碼建議放在哪裡?

建議放進輕量的自訂外掛或 mu-plugins 資料夾,別放進佈景主題的 functions.php;換主題不會移除已寫進資料庫的角色,但若角色靠 functions.php 建立,換主題後程式碼就消失,之後想調整或移除都找不到源頭。

怎麼讓編輯角色也能管理外掛更新?

不必新增角色,用 get_role(‘editor’) 拿到角色物件後呼叫 add_cap(),加上 activate_plugins 與 update_plugins 兩項能力,編輯就能協助處理外掛更新,不必動用系統管理員帳號。