本文主要以 MySQL 和 OceanBase 對比的方式,來介紹 OceanBase(MySQL 模式)安全體系中關於身份鑑別的相關內容,包括身份鑑別機制、用戶名組成、密碼複雜度、密碼過期策略等。
作者:金長龍
愛可生測試工程師,負責 DMP 產品的測試工作。
用戶鑑權
OceanBase下的身份鑑別機制
OceanBase 數據庫目前只支持密碼驗證方式,使用的是 MySQL Authentication Protocol(MAPI) 協議進行用戶鑑權。該協議基於客戶端機器上的 MySQL 客戶端帳戶完成身份驗證,要求客戶端具有正確的用戶名和密碼才能連接到 OceanBase 服務器。下面是身份鑑權的具體過程:
- 客戶端發起連接請求到 OceanBase 服務器
- OceanBase 服務器發送隨機字符串 (Nonce) 給客戶端
- 客戶端使用發送來的隨機字符串以及正確的用戶名和密碼,進行哈希加密計算
- 客戶端將加密後的 Token 發送回 OceanBase 服務器
- OceanBase 服務器驗證客戶端發送的解碼結果是否正確
- 如果解碼結果正確,OceanBase 服務器允許客戶端連接服務器;否則拒絕連接請求
注意: OceanBase 數據庫當前支持的 MySQL 客戶端版本爲 5.5、5.6 和 5.7。當使用 MySQL 8.0 客戶端連接 OceanBase 時,需要在連接命令上加
–default_auth=mysql_native_pasowrd
。原因是 MySQL 5.6、MySQL 5.7 的默認加密算法是mysql_native_password
,而 MySQL 8.0 的默認加密算法是caching_sha2_password
。
用戶命名
用戶命名規則
- 一個
user
由user_name
和host
共同組成,這點 MySQL 和 OceanBase 是一致的; - MySQL 用戶名不能超過 32 個字符,OceanBase 用戶名不能超過 64 個字符。
下面我們看兩個命名規則的例子。
使用舉例
用戶名的組成
用戶名都是 u1
但 host
不同,代表着三個不同用戶。
create user 'u1'@'%' identified by '123456';
create user 'u1'@'localhost' identified by '123456';
create user 'u1'@'127.0.0.1' identified by '123456';
通過 current_user()
函數查詢當前登錄用戶,可以看到用戶標識爲 user_name@host
。
長度限制
創建用戶時,用戶名長度超出限制,MySQL 和 OceanBase 的報錯一致,提示 too long for user name
。
MySQL
OceanBase
注意:這裏的提示語部分有誤,後續版本修復。
密碼強度評定
爲了防止惡意的密碼攻擊,OceanBase 和 MySQL 都提供設置密碼複雜度的相關功能,以此來提升數據庫的安全性。 OceanBase 和 MySQL 分別通過如下的一系列變量限制密碼的複雜度規則。
# OceanBase 4.1
obclient [oceanbase]> SHOW VARIABLES LIKE "validate_password%";
+--------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------+-------+
| validate_password_check_user_name | on |
| validate_password_length | 0 |
| validate_password_mixed_case_count | 0 |
| validate_password_number_count | 0 |
| validate_password_policy | low |
| validate_password_special_char_count | 0 |
+--------------------------------------+-------+
6 rows in set (0.003 sec)
# MySQL 8.x
mysql [localhost:8031] {msandbox} ((none)) > SHOW VARIABLES LIKE "validate_password%";
+--------------------------------------+--------+
| Variable_name | Value |
+--------------------------------------+--------+
| validate_password.check_user_name | ON |
| validate_password.dictionary_file | |
| validate_password.length | 8 |
| validate_password.mixed_case_count | 1 |
| validate_password.number_count | 1 |
| validate_password.policy | MEDIUM |
| validate_password.special_char_count | 1 |
+--------------------------------------+--------+
7 rows in set (0.00 sec)
差異對比
對比項 | OceanBase | MySQL |
---|---|---|
安裝方式 | 自帶系統變量,可以直接配置。 | 需要先安裝 validate_password 組件(INSTALL COMPONENT 'file://component_validate_password';),然後纔可以使用相關變量做密碼限制> |
參數個數 | 6 個系統變量,沒有變量 validate_password.dictionary_file |
7 個系統變量。 其中的 validate_password.dictionary_file 變量僅在 validate_password.policy=STRONG 時纔會生效(目前 oceanbase 不支持 STRONG 策略)。 |
validate_password.policy 變量值 |
支持配置 LOW、MEDIUM 兩種密碼檢查策略 | 支持配置 LOW, MEDIUM, STRONG 三種密碼檢查策略;其中 STRONG 就是在 MEDIUM 策略的基礎上增加了字典文件的檢查。 |
兩種數據庫的參數默認值大部分都不同,使用中需要注意。
密碼過期策略
主要包括手動設置密碼過期和設置全局的密碼過期策略。
MySQL
支持手動設置用戶密碼過期。
# 手動設置密碼過期
mysql [localhost:8031] {msandbox} ((none)) > alter user 'jeffrey'@'%' PASSWORD EXPIRE;
Query OK, 0 rows affected (0.04 sec)
# 密碼過期後執行語句受限
mysql [localhost:8031] {jeffrey} ((none)) > show databases;
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
支持設置全局的密碼過期策略:可以使用 default_password_lifetime
系統變量。
OceanBase
目前暫不支持。
登錄失敗處理
對於多次登錄失敗的用戶,數據庫會鎖定該用戶,以便防止惡意的密碼攻擊,從而保護數據庫,提升數據庫的安全性。
OceanBase
OceanBase 設計了幾個租戶級的參數,用來控制用戶連續錯誤登錄的次數以及賬戶的鎖定時間。這是 OceanBase 特有而 MySQL 沒有的。主要是以下三個參數,可以通過命令查詢(SHOW PARAMETERS LIKE "connection_control_%";
)。
- connection_control_failed_connections_threshold:指定用戶連續錯誤登錄的次數
- connection_control_min_connection_delay:達到錯誤登錄次數之後鎖定用戶的最小時長
- connection_control_max_connection_delay:達到錯誤登錄次數之後鎖定用戶的最大時長
在每次登錄失敗時,OBServer 日誌都會有相應的記錄。
[root@31aa8013555f log]# grep "denied" observer.log
[2023-05-04 09:32:18.689329] WDIAG [SERVER] load_privilege_info (obmp_connect.cpp:553) [782][MysqlQueueTh5][T1][Y0-0005FA34D4B800AC-0-0] [lt=11][errcode=-4043] User access denied(login_info={tenant_name:"sys", user_name:"root", client_ip:"127.0.0.1", db:"oceanbase", scramble_str:"?sE@PP"WqS*v7KUJQ8cj"}, ret=-4043)
另外也截了一段登錄成功時的日誌。
[2023-05-23 09:07:52.658015] INFO [SERVER] process (obmp_connect.cpp:369) [12383][MysqlQueueTh1][T1][Y0-0005FBC67C77F146-0-0] [lt=9] MySQL LOGIN(direct_client_ip="127.0.0.1", client_ip=127.0.0.1, tenant_name=sys, tenant_id=1, user_name=u1, host_name=%, sessid=3221576719, proxy_sessid=0, sess_create_time=0, from_proxy=false, from_java_client=false, from_oci_client=true, from_jdbc_client=false, capability=150974085, proxy_capability=49408, use_ssl=true, c/s protocol="OB_2_0_CS_TYPE", autocommit=true, proc_ret=0, ret=0)
MySQL
從 MySQL 8.0.19 開始,可以在 create user
和 alter user
語句中使用 FAILED_LOGIN_ATTEMPTS
和 PASSWORD_LOCK_TIME
選項爲每個帳戶配置所需的登錄失敗次數和鎖定時間。
- FAILED_LOGIN_ATTEMPTS:指定連續錯誤密碼的次數
- PASSWORD_LOCK_TIME:達到錯誤登錄次數之後的鎖定時長(單位天)
使用舉例
CREATE USER 'u1'@'localhost' IDENTIFIED BY 'password'
FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 3;
ALTER USER 'u2'@'localhost'
FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME UNBOUNDED;
小結
OceanBase (MySQL 模式)在安全審計的身份鑑別方面與 MySQL 功能基本一致。
關於 SQLE
愛可生開源社區的 SQLE 是一款面向數據庫使用者和管理者,支持多場景審覈,支持標準化上線流程,原生支持 MySQL 審覈且數據庫類型可擴展的 SQL 審覈工具。