数据库的第一道防线:从金仓KES看企业级身份验证体系的设计逻辑
每次跟人聊数据库安全,我总喜欢问一个问题:你觉得数据库安全最重要的一环是什么?
答案五花八门。有人说是加密,有人说是审计,有人说是备份恢复。这些当然都重要,但在我看来,最重要也最容易被低估的,其实是身份验证------也就是确认"你是谁"的那个环节。
为什么这么说?因为身份验证是数据库的第一道门。门如果没守好,后面的一切防御都形同虚设。加密再强,挡不住合法用户用合法账号干坏事;审计再细,记录的都是"已授权"的操作;备份再全,也恢复不了被盗的数据。
今天,我们就从金仓数据库KES的身份验证体系入手,聊聊企业级数据库应该怎么守住这道门。
一、身份验证的本质:不只是"输入密码"
很多人对身份验证的理解停留在"用户名+密码"这个层面。但在企业级数据库里,身份验证要复杂得多。
金仓数据库的身份验证体系,可以拆成三个层面来看:
第一层:你是谁?------用户身份的确认。这是最基础的层面,通过用户名和密码(或其他凭证)来验证。
第二层:你能从哪儿来?------来源的限制。只允许特定IP、特定时间段的连接请求。
第三层:你的凭证够不够强?------口令强度的管理。密码不能太简单,不能长期不换,不能跟历史密码重复。
三层叠加,才构成一个相对完整的企业级身份验证体系。
二、口令保护:不只是"存好密码"
先说说最基础的口令保护。很多人觉得,密码存在数据库里,加密一下不就行了?但实际要考虑的问题远不止这些。
2.1 加密算法的选择
金仓支持多种口令加密算法,每种都有适用的场景:
sql
-- 查看当前口令加密算法
SHOW password_encryption;
-- 设置为国密SM3算法
ALTER system SET password_encryption = 'sm3';
SELECT sys_reload_conf();
- scram-sha-256:标准的SCRAM认证,挑战-响应机制,防止口令在网络中被嗅探
- sm3:国密算法,符合国内合规要求
- scram-sm3:国密版的SCRAM认证,结合了两者优势
- sm4:基于国密算法的更高级加密
选择哪种算法,取决于你的合规要求。如果是普通企业,scram-sha-256足够安全;如果是政府或金融机构,可能需要启用国密算法。
2.2 口令密文的存储
除了加密算法,还有个实际问题是:密码在传输过程中怎么保护?金仓提供了sys_encpwd工具,可以把用户密码以密文形式存储在一个专门的配置文件中:
bash
# 配置sao用户的密码
./sys_encpwd -H 127.0.0.1 -P 54321 -D security -U sao -W 12345678abc
# 支持通配符匹配
./sys_encpwd -H \* -P 54321 -D \* -U sao -W 12345678abc
配置完成后,密码会以密文形式存在.encpwd文件中,即使有人拿到了这个文件,也无法直接获取明文密码。
三、口令复杂度:别让用户设"123456"
做过运维的都知道,最头疼的不是技术问题,而是用户设的密码太简单。"123456"、"password"、"admin",这些密码在系统里一抓一大把。
金仓通过passwordcheck插件来解决这个问题。这个插件可以配置一系列密码复杂度规则:
sql
-- 加载插件
CREATE EXTENSION passwordcheck;
-- 由安全管理员开启密码复杂度检查
\c - sso
ALTER system SET passwordcheck.enable = on;
SELECT sys_reload_conf();
-- 设置密码最小长度为10
ALTER system SET passwordcheck.password_length = 10;
-- 设置密码至少包含3个字母
ALTER system SET passwordcheck.password_condition_letter = 3;
-- 设置密码至少包含3个数字
ALTER system SET passwordcheck.password_condition_digit = 3;
-- 设置密码至少包含2个特殊字符
ALTER system SET passwordcheck.password_condition_punct = 2;
-- 设置密码至少包含1个大写字母
ALTER system SET passwordcheck.password_condition_upper = 1;
设置完之后,再创建用户时,如果密码不符合规则,就会被拒绝:
sql
-- 这个会失败,密码长度只有5
CREATE USER u1 WITH PASSWORD '123ab';
ERROR: password length 5 is too short, should be longer than min password length 10.
-- 这个会失败,没有数字
CREATE USER u1 WITH PASSWORD 'abcdefghij';
ERROR: Password should contain at least 3 digit and the current number is 0
-- 这个会失败,没有特殊字符
CREATE USER u1 WITH PASSWORD '1234567890abc';
ERROR: Password should contain at least 2 punct and the current number is 0
-- 终于成功
CREATE USER u1 WITH PASSWORD '1234567890abc./';
这套机制的好处是:把安全策略从"人治"变成了"法治"。不用再靠运维人员口头叮嘱"密码设复杂点",系统会自动强制执行。
四、口令生命周期:密码不能"终身制"
密码设得再复杂,如果一直不换,也存在风险。金仓提供了口令有效期管理功能,让密码有"保质期"。
4.1 密码有效期设置
通过identity_pwdexp插件,可以配置密码的有效期:
sql
-- 加载插件
CREATE EXTENSION identity_pwdexp;
-- 由安全管理员设置密码有效期为7天
\c - sso
ALTER system SET identity_pwdexp.password_change_interval = 7;
SELECT sys_reload_conf();
-- 设置最大密码有效期(不能超过这个值)
ALTER system SET identity_pwdexp.max_password_change_interval = 30;
配置之后,新创建的用户会自动获得一个有效期。也可以在创建用户时手动指定:
sql
-- 创建用户时指定密码有效期
CREATE USER temp_user WITH PASSWORD '12345678abc'
VALID UNTIL '2026-12-31 23:59:59';
密码过期后,用户会被限制登录,必须修改密码才能继续使用。这个机制可以防止密码被长期使用带来的风险。
4.2 口令历史管理
还有一个常见问题是:用户换密码时,经常在"123456"、"1234567"、"12345678"之间循环。这样换密码等于没换。
金仓的passwordhistory插件可以防止这种情况:
sql
-- 加载插件
CREATE EXTENSION passwordhistory;
-- 开启口令历史功能
\c - sso
ALTER system SET passwordhistory.enable = on;
SELECT sys_reload_conf();
-- 设置历史记录天数为2天
ALTER system SET passwordhistory.password_time = 2;
设置之后,用户修改密码时,系统会检查新密码在指定天数内是否使用过:
sql
-- 创建用户
CREATE USER u1 WITH PASSWORD '12345678abc';
-- 尝试改回相同密码,会失败
ALTER USER u1 WITH PASSWORD '12345678abc';
ERROR: The password has been used recently.
这个机制强制用户使用全新的密码,而不是在几个旧密码之间来回切换。
五、异常登录防护:当有人试图暴力破解
密码设得再复杂,也防不住暴力破解------攻击者不断尝试不同的密码组合,总有可能撞上一个。
金仓的sys_audlog插件提供了账户异常登录锁定功能:
sql
-- 加载插件
CREATE EXTENSION sys_audlog;
-- 由安全管理员配置
\c - sso
-- 设置最大失败次数为6
ALTER system SET sys_audlog.max_error_user_connect_times = 6;
-- 设置连续失败6次后锁定
ALTER system SET sys_audlog.error_user_connect_times = 6;
-- 设置锁定时间为60分钟
ALTER system SET sys_audlog.error_user_connect_interval = 60;
SELECT sys_reload_conf();
配置之后,如果一个用户在60分钟内连续6次登录失败,账户会被自动锁定。锁定期间,即使输入正确密码也无法登录。
需要解锁时,可以由安全管理员手动处理:
sql
-- 手动解锁用户
\c - sso
ALTER USER username WITH LOGIN;
这个机制可以有效防御暴力破解攻击。攻击者尝试几次之后账户就被锁了,没法继续试。
六、登录信息显示:让用户知道谁动过自己的账号
除了被动防御,主动提示也是安全的重要一环。金仓的sys_audlog插件可以记录登录信息,并在用户登录时显示:
sql
-- 设置登录信息记录级别为2(记录成功和失败)
\c - sso
ALTER system SET sys_audlog.user_logonlog_level = 2;
SELECT sys_reload_conf();
设置之后,用户的登录信息会被记录在系统表中:
sql
-- 普通用户查看自己的登录信息
SELECT * FROM sys_audlog.sys_user_audit_userlog;
user_name | host | logon_time | logon_status | times
-----------+-----------+-------------------------------+--------------+-------
user1 | 127.0.0.1 | 2024-05-23 18:15:16.029321+00 | SUCCESSFUL | 6
user1 | 127.0.0.1 | 2024-05-23 18:15:11.761478+00 | FAILED | 5
user1 | 127.0.0.1 | 2024-05-23 18:13:48.545484+00 | FAILED | 4
用户登录时可以看到上次登录的时间、IP,以及这段时间内有多少次失败尝试。如果发现异常,可以及时察觉。
七、弱口令扫描:主动排查安全隐患
前面的机制都是被动防御------在用户设置密码时检查。但历史遗留的用户可能已经设了弱口令,怎么办?
金仓的security_utils插件提供了弱口令扫描功能:
sql
-- 加载插件
CREATE EXTENSION security_utils;
-- 开启弱口令检查
\c - sso
ALTER system SET security_utils.weak_pwd_check_enable = on;
SELECT sys_reload_conf();
-- 配置弱口令字典
\c - system
SET WEAK PASSWORD '123456';
SET WEAK PASSWORD 'password';
SET WEAK PASSWORD 'admin123';
SET WEAK PASSWORD 'qwerty';
-- 查看当前弱口令字典
SELECT * FROM security_utils.weak_pwd_dic;
配置好弱口令字典后,可以主动扫描所有用户:
sql
-- 扫描弱口令用户
SELECT * FROM security_utils.weak_passwd_scan_result;
username | weak_passwd
----------+-------------
u1 | 123456
u2 | password
(2 rows)
扫描结果会列出所有使用弱口令的用户。管理员可以根据这个列表,通知相关用户修改密码,或者直接强制重置。
八、来源限制:谁能从哪儿来
除了"你是谁",还要问"你能从哪儿来"。金仓的src_restrict插件提供了来源限制功能,可以设置黑白名单:
sql
-- 添加白名单规则:允许user1从11.11.11.*网段登录
SELECT src_restrict.add_rules(
0, -- 0表示白名单
'user1', -- 用户名
'11.11.11.*', -- 允许的IP
'', -- 不受限制的IP
'ip_range=11.11.11.10~11.11.11.30;' || -- IP段限制
'time_range=09:00:00~18:00:00' -- 时间段限制
);
-- 添加黑名单规则:禁止u2从10.12.1.0网段登录
SELECT src_restrict.add_rules(
1, -- 1表示黑名单
'u2', -- 用户名
'10.12.1.0', -- 禁止的IP
'', -- 不受限制的IP
''
);
-- 查看当前规则
SELECT * FROM src_restrict.show_rules;
黑白名单同时生效时,黑名单优先级更高。这个机制可以实现精细的访问控制------比如只允许运维人员在办公网登录,只允许应用服务器访问特定账号。
九、空闲连接断开:释放资源,减少风险
最后一个容易被忽略的点:空闲连接。一个连接建立后,如果用户离开电脑忘了退出,这个连接就可能成为安全隐患。
金仓的client_idle_timeout参数可以解决这个问题:
sql
-- 当前会话设置5分钟空闲断开
SET client_idle_timeout = 300;
-- 全局设置30分钟空闲断开
ALTER system SET client_idle_timeout = 1800;
SELECT sys_reload_conf();
设置之后,如果连接空闲超过指定时间,会被自动断开。需要继续操作时,必须重新连接。这个机制既释放了数据库资源,也减少了因用户忘记退出带来的风险。
十、总结:身份验证的"纵深防御"
回头看金仓这套身份验证体系,可以总结出几个特点:
第一,多层次防御。不是只靠一个密码,而是密码复杂度、有效期、历史记录、异常锁定、来源限制等多个层次叠加。
第二,主动与被动结合。既有被动防御(登录时检查),也有主动排查(弱口令扫描)。
第三,精细控制。可以对不同用户设置不同策略,可以对来源IP、时间段进行限制。
第四,可追溯。登录信息被完整记录,用户可以查看自己的登录历史,发现异常。
这套体系的设计理念,可以用一句话概括:身份验证不是一道门,而是一个系统。门只要打开一次就可能被攻破,系统则需要层层突破。这正是企业级数据库应有的安全设计。
更多关于数据库身份验证和安全管理的技术细节,欢迎访问金仓数据库官方技术博客:kingbase.com.cn