本文作者:金长龙爱可生测试工程师,负责 DMP 产品的测试工作。
本文以MySQL为参照,详细阐述了OceanBase 在MySQL模式下的安全体系中,身份鉴别的能力,涵盖了身份鉴别机制、用户名的构成规则、密码的复杂度,以及密码过期策略的等方面。
用户鉴权
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 功能基本一致。