一般来说数据库密码安全管理要考虑以下几个方面 :
1. 密码过期策略,决定密码的有效期,多长时间过期.Postgresql不支持密码过期策略,但是可以通过其他方式来实现过期提醒.
Postgresql 不支持密码复用策略,但是可以通过其他方式来实现强制密码复用策略.
Postgresql 不支持密码长度策略,但是可以通过其他方式来实现强制密码长度策略.
Postgresql 不支持密码复杂度策略,但是可以通过其他方式来实现强制密码复杂度策略.
Postgresql 不支持密码字典过滤策略,但是可以通过其他方式来实现强制字典过滤策略.
加密存储在创建用户时使用encrypted password即可.
如果设置了password_encryption=off,同时创建用户时不加encrypted,那么密码将以明文存储.
例如 :
加密存储 :
digoal=# create role u1 login encrypted password 'digoal';
CREATE ROLE
digoal=# select * from pg_shadow where usename='u1';
usename | usesysid | usecreatedb | usesuper | usecatupd | userepl | passwd | valuntil | useconfig
---------+----------+-------------+----------+-----------+---------+-------------------------------------+----------+-----------
u1 | 26383 | f | f | f | f | md5bdf22a6622939c7c7ab2377eaca514d5 | |
(1 row)
明文存储 :
digoal=# set password_encryption=off;
SET
digoal=# create role u2 login password 'digoal';
CREATE ROLE
digoal=# select * from pg_shadow where usename='u2';
usename | usesysid | usecreatedb | usesuper | usecatupd | userepl | passwd | valuntil | useconfig
---------+----------+-------------+----------+-----------+---------+--------+----------+-----------
u2 | 26387 | f | f | f | f | digoal | |
(1 row)
8. 密码保护策略,密码输入错误多少次后延迟认证. 可用来防止暴力破解. Postgresql 不支持密码保护策略. 目前Postgresql在密码管理这块做得较弱,以下举例通过函数来实现其中的部分安全策略 : 创建一个字典表,用于存放已经使用过的密码的md5值,以及用来进行暴力破解的密码字典的md5值. digoal=# create table pwd_dictionary(pwd text unique); CREATE TABLE 创建一个记录用户最后一次修改密码时间的表. 用于实施密码过期提醒策略. digoal=# create table user_pwd(rolename name not null unique,pwd_modify_time timestamp not null); CREATE TABLE 创建用户的函数 : digoal=# create or replace function create_role(i_rolename name,i_pwd text) returns void as $$ declare v_length int := 8; begin -- 密码长度策略 if length(i_pwd) < v_length then raise notice 'password too short,please use password long than %.',v_length; return; end if; -- 密码复杂度策略,包含数字,字母大小写. if not(i_pwd ~ '[a-z]' and i_pwd ~ '[A-Z]' and i_pwd ~ '[0-9]') then raise notice 'password too simple,please ensure password contain a-z,A-Z and 0-9.'; return; end if; -- 密码复用策略,不允许重复使用已经存在的密码. -- 密码字典策略,不允许使用密码字典中的密码. insert into pwd_dictionary(pwd) values (md5(i_pwd)); -- 插入用户表,记录用户最后一次修改密码的时间,用于密码过期策略 insert into user_pwd(rolename,pwd_modify_time) values (i_rolename,now()); -- 创建用户 execute 'create role '||i_rolename||' encrypted password '||quote_literal(i_pwd); raise notice 'create role % successed.',i_rolename; return; end; $$ language plpgsql strict; CREATE FUNCTION 创建用户密码过短,不允许创建. digoal=# select * from create_role('u4','pwd'); NOTICE: password too short,please use password long than 8. create_role ------------- (1 row) 创建用户密码过于简单,'abcdefee'); NOTICE: password too simple,A-Z and 0-9. create_role ------------- (1 row) 创建用户正常. digoal=# select * from create_role('u4','aA0ffffffff'); NOTICE: create role u4 successed. create_role ------------- (1 row) 创建用户密码与现有密码重复,不允许创建. digoal=# select * from create_role('new','aA0ffffffff'); ERROR: duplicate key value violates unique constraint "pwd_dictionary_pwd_key" DETAIL: Key (pwd)=(2b9aa88182d13d35930180b4cc791beb) already exists. CONTEXT: sql statement "insert into pwd_dictionary(pwd) values (md5(i_pwd))" PL/pgsql function create_role(name,text) line 17 at sql statement 修改用户密码的函数 : digoal=# create or replace function alter_role_pwd(i_rolename name,不允许使用密码字典中的密码. insert into pwd_dictionary(pwd) values (md5(i_pwd)); -- 更新用户表,用于密码过期策略 update user_pwd set pwd_modify_time=now() where rolename=i_rolename; -- 修改用户密码 execute 'alter role '||i_rolename||' encrypted password '||quote_literal(i_pwd); raise notice 'modify role % password successed.',i_rolename; return; end; $$ language plpgsql strict; CREATE FUNCTION 使用该函数修改用户密码 digoal=# select * from alter_role_pwd('u4','new'); NOTICE: password too short,please use password long than 8. alter_role_pwd ---------------- (1 row) digoal=# select * from alter_role_pwd('u4','new22222222'); NOTICE: password too simple,A-Z and 0-9. alter_role_pwd ---------------- (1 row) digoal=# select * from alter_role_pwd('u4','new2222222z2'); NOTICE: password too simple,'new2222222z2A'); NOTICE: modify role u4 password successed. alter_role_pwd ---------------- (1 row) digoal=# select * from alter_role_pwd('u4','new2222222z2A'); ERROR: duplicate key value violates unique constraint "pwd_dictionary_pwd_key" DETAIL: Key (pwd)=(9a5c46207db775d4d98e64d427481cbc) already exists. CONTEXT: sql statement "insert into pwd_dictionary(pwd) values (md5(i_pwd))" PL/pgsql function alter_role_pwd(name,text) line 17 at sql statement 密码过期提醒 : 因为密码最后一次修改时间已经更新到user_pwd表,所以结合这个可以在系统crontab中或者nagios监控软件中实施密码过期提醒. digoal=# select * from user_pwd ; rolename | pwd_modify_time ----------+---------------------------- u4 | 2013-05-25 18:21:59.376404 (1 row) [小结] 1. 为了密码安全性,在Postgresql 中,创建用户请使用create_role函数,不要直接使用create role 命令. 2. 修改用户密码请使用alter_role_pwd函数. 不要直接使用alter role 命令. 3. 密码过期提醒请结合nagios软件或者操作系统crontab来实现邮件提醒数据库管理员. 原文链接:https://www.f2er.com/postgresql/196108.html