鐵人賽的進度默默地來到第 19 篇,也即將踏入開發 WordPress 外掛的篇章,期待大家即將身為外掛開發者,必須對安全性的議題非常關注,對自己寫的外掛程式權限的控管要非常小心,這是基本的責任感。
今天的主要介紹的就是 WordPress 系統中的角色與權限,熟悉今天介紹的權限管控相關的函式之後,設計外掛時遇到操作新增、修改、刪除等功能的情境,別忘了檢查使用者的角色與權限,為網站的安全性把關。
WordPress 為了實現不同使用者的有不同的登入或管理權限,實作了一個稱為「使用者角色」(user roles) 的功能,讓網站管理員可以根據使用者的貢獻度和職責分配不同的訪問和管理權限。
以下是 WordPress 中幾個主要的使用者角色及其基本權限。
中文 | 英文 | 大略說明 |
---|---|---|
管理員 | Administrator | 能夠訪問到網站的所有管理功能。可以新增、編輯或刪除所有內容和使用者。 |
編輯 | Editor | 可以發布和管理包括其他使用者的文章在內的所有內容。無法修改網站的設定和使用者權限。 |
作者 | Author | 可以發布和管理自己的文章。無法管理其他用戶的內容或進行網站的設置變更。 |
貢獻者 | Contributor | 可以撰寫自己的文章,但不能直接發布。需要提交他們的內容供編輯者或管理員審核。無法上傳檔案。 |
訂閱者 | Subscriber | 通常只有限制的後台登入,主要是用來管理他們的使用者個人資料。無法發布文章或修改網站內容。 |
這些主要的使用者角色是系統內建的,從 WordPress 2.0 版開始,定義在 wp-admin\includes\schema.php
中的 populate_roles
函式中,隨著 WordPress 的功能越來越多,陸續加入新的權限以供使用。
圖:schema.php 程式碼片段
例如,第 24 行至 28 行,使用 add_role
函式加入這 5 種基本的角色。
每個使用者角色基本上是一組權限的集合。這些權限 (capabilities) 確定了一個使用者角色可以(或不能)在網站上執行的操作。例如,管理員有權限安裝外掛,而作者則沒有這個權限。
圖:schema.php 程式碼片段
同樣在 schema.php 中再往下滑一些。看到第 15 行,使用 get_role
函式取出 WP_Role
實例後,再使用這個類別的 add_cap
方法,陸續加入權限。
WordPress 的這種使用者角色分配的方式,允許網站管理者很靈活地控制不同使用者對網站的登入和管理權限,有秩序性地保持網站的日常管理。而且,通過外掛或客製化的程式碼,你還可以自行定義角色及調整不同角色的權限。
在 WordPress 中,使用者角色和權限的資料是存放在資料庫的 wp_options
表中,而一個名為 wp_user_roles
的欄位中,以 PHP 序列化資料的格式儲存。
圖:資料表 wp_options
當你使用像是 add_role
、add_cap
等函數時,WordPress 會處理這些資料並將其存放在 wp_options
表中。當你在網站上添加新角色或修改現有角色的權限時,相對應的資料會被更新。
雖然可以用 get_option( 'wp_user_roles' )
可以從資料庫中獲取所有使用者角色和它們對應的權限。再使用 update_option( 'wp_user_roles', $new_roles )
來更新儲存在資料庫中的使用者角色資料。不過 WordPress 有提供內建的函式來處理這個欄位的值,以確保格式正確,就沒以直接存取這個欄位的理由囉。
至於個別使用者的角色為何?則是定義在 usermeta 中。
圖:資料表 wp_usermeta
一個名為 wp_capabilities
的欄位定義該使用者的角色。
另一個 wp_user_level
欄位定義該使用者的等級。
我們得知 WordPress 的使用者角色和權限資料存放在 wp_options
資料表,以及個別使用者的角色存放在 wp_usermeta
資料表,對資料的歸屬有概念後,對相關函式的操作能更理解它的作用。
add_role( 'ironman' )
如果想建立一個鐵人角色,當然也可以唷!
$role = get_role( 'ironman' )
這會取得角色名稱為 ironman
的 WP_Role 實例,可以用這個實例所定義的方法來為該角色進行權限的新增、修改、刪除等動作。
在前一個 get_role 函式的說明中提到的類別名稱。
方法 | 說明 |
---|---|
add_cap | 給角色分配一個權限。 |
has_cap | 判定角色是否具有給定的權限。 |
remove_cap | 從角色中移除一個權限。 |
以下是一個簡單的例子,示範了如何使用 add_cap()
函數給我們剛剛建立的「鐵人」角色新增一個新的權限,讓它可以發表文章。
圖:為角色加入權限
使用 WP_User 類別實例化之後的物件,擁有以下方法,可以為該使用者設定角色:
方法 | 說明 |
---|---|
set_role | 為使用者設定角色。 |
add_role | 為使用者新增角色。 |
remove_role | 把角色從使用者移除。 |
$current_user = wp_get_current_user();
$roles = ( array ) $current_user->roles;
$roles
是一個包含用戶所有角色的陣列。
$user_id = 1; // 假設用使用者 ID 為1
$user = new WP_User( $user_id );
$user->set_role( 'editor' );
這會將用使用者 ID 為 1 的使用者的角色設置為編輯。
$user->add_role( 'ironman' );
這將給使用者新增一個名為 ironman
的角色(前提是這個角色已經被定義)。
$user->remove_role( 'ironman' );
這將從使用者的角色列表中移除 ironman
角色。
本篇提到的函式和類別方法關於「新增」、「刪除」這兩種動作,程式碼會操作資料庫,必須註冊在像是「保存設定」之類的後台頁面,或啟用外掛時的鉤點,而不是 init
這類每次讀取頁面都會觸發的鉤點。它只要一次性的變更,存在資料庫後就永久生效。本篇文章示範註冊在 init
是為了讓讀者們練習時能立即看到效果的簡便寫法。
相信今天的文章能讓大家充份認識 WordPress 的使用者角色如何定義,以及如何使用 WP_Role 類別來操作權限,並瞭解 WP_User 類別如何為使用者新增、刪除角色。
坊間的權限管理外掛也只是利用這些 WordPress 的內建類別及函式來做處理而已,並不是什麼神奇的魔法。瞭解了細節的作法後,或許也沒有必要裝一個肥肥的權限管理外掛,自己可以客製一個符合自己需求的外掛,追求效能和方便性的平衡,也是玩 WordPress 的樂趣哦。
課後思考:
思考並說明如何確保在調整角色和權限時,不會無意中給予使用者過多的存取權限,從而危及網站安全。
前篇解答參考:
為了達成某種便利,而刻意繞過核心的機制不是良好的習慣。正確的作法,筆者的建議會是設計一個傳統的 AJAX 入口以取得 nonce,由前端儲存在 Session Storage,每次 JavaScript 對 REST API 請求的時候都帶上 nonce。當 nonce 失效時再對提供 nonce 的 AJAX 入口發出請求來更新 Session Storage 中的 nonce 值。