利用AI编码增强PostgreSQL密码校验
前言
最近有朋友讲PostgreSQL的密码强度校验太弱了,尽管自带了passwordcheck插件,但还是只能校验简单的场景。
原理简介
passwordcheck密码校验仅支持一些简单场景:
1、密码不能等于用户名
2、密码长度不低于MIN_PWD_LENGTH(默认为8)
3、密码中不能包含用户名
4、密码必须同时包含字母和非字母
5、使用cracklib来校验密码,和cracklib字典设置有关
staticvoid
check_password(constchar*username,
constchar*shadow_pass,
PasswordType password_type,
Datum validuntil_time,
bool validuntil_null)
{
if(prev_check_password_hook)
prev_check_password_hook(username, shadow_pass,
password_type, validuntil_time,
validuntil_null);
if(password_type != PASSWORD_TYPE_PLAINTEXT)
{
/*
* Unfortunately we cannot perform exhaustive checks on encrypted
* passwords - we are restricted to guessing. (Alternatively, we could
* insist on the password being presented non-encrypted, but that has
* its own security disadvantages.)
*
* We only check for username = password.
*/
constchar*logdetail = NULL;
/* 密码不能等于用户名 */
if(plain_crypt_verify(username, shadow_pass, username,&logdetail)== STATUS_OK)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("password must not equal user name")));
}
else
{
/*
* For unencrypted passwords we can perform better checks
*/
constchar*password = shadow_pass;
int pwdlen = strlen(password);
int i;
bool pwd_has_letter,
pwd_has_nonletter;
#ifdef USE_CRACKLIB
constchar*reason;
#endif
/* 密码长度不低于MIN_PWD_LENGTH(默认为8)*/
/* enforce minimum length */
if(pwdlen < MIN_PWD_LENGTH)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("password is too short")));
/* 密码中不能包含用户名 */
/* check if the password contains the username */
if(strstr(password, username))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("password must not contain user name")));
/* check if the password contains both letters and non-letters */
pwd_has_letter =false;
pwd_has_nonletter =false;
for(i =0; i < pwdlen; i++)
{
/*
* isalpha() does not work for multibyte encodings but let's
* consider non-ASCII characters non-letters
*/
if(isalpha((unsignedchar) password[i]))
pwd_has_letter =true;
else
pwd_has_nonletter =true;
}
/* 密码必须同时包含字母和非字母 */
if(!pwd_has_letter ||!pwd_has_nonletter)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("password must contain both letters and nonletters")));
#ifdef USE_CRACKLIB
/* call cracklib to check password */
if((reason =FascistCheck(password, CRACKLIB_DICTPATH)))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("password is easily cracked"),
errdetail_log("cracklib diagnostic: %s", reason)));
#endif
}
/* all checks passed, password is ok */
}
被吐槽了,这个密码安全性校验也太差了?连个字母大小写都没判断?
我给朋友说改插件呗,源码都在手里了,你想怎么改就怎么改,这就是PG的优势。
代码实现
刚好有空,自己想在之前的功能基础上实现一下校验密码同时包含大小写字母。突然想到AI不是挺猛吗,让AI来写一下试试水。
输入一句“C语言,判断一个字符串是否同时包含大小写字母”,隔了几秒就出结果了,不仅给了函数定义,还给了解释和注意事项。
函数定义
bool contains_both_cases(constchar*str);
/* check if the password contain both uppercase and lowercase letters */
bool
contains_both_cases(constchar*str)
{
bool has_upper =false, has_lower =false;
for(int i =0; str[i]; i++){
if(isupper((unsignedchar)str[i])){
has_upper =true;
}
if(islower((unsignedchar)str[i])){
has_lower =true;
}
if(has_upper && has_lower){
returntrue;
}
}
returnfalse;
}
在check_password函数中调用,进行大小写字母校验
staticvoid
check_password(constchar*username,
constchar*shadow_pass,
PasswordType password_type,
Datum validuntil_time,
bool validuntil_null)
{
/* 省略部分代码行 */
#ifdef USE_CRACKLIB
/* call cracklib to check password */
if((reason =FascistCheck(password, CRACKLIB_DICTPATH)))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("password is easily cracked"),
errdetail_log("cracklib diagnostic: %s", reason)));
#endif
/* check if the password contain both uppercase and lowercase letters */
if(!contains_both_cases(password))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("password must contain both uppercase and lowercase letters")));
}
/* all checks passed, password is ok */
}
重新编译passwordcheck,重启数据库。
测试验证
进行用户密码校验,可以看到已经可以校验密码是否同时包含大小写字母。
当然也可以继续加入必须包含特殊字符校验,感兴趣的朋友可以自行修改。
postgres=# create user testuser password '123';
ERROR: password is too short
postgres=# create user testuser password '12345678';
ERROR: password must contain both letters and nonletters
postgres=# create user testuser password 'testuser';
ERROR: password must not contain user name
postgres=# create user testuser password '1234qwer';
ERROR: password must contain both uppercase and lowercase letters
postgres=# create user testuser password '1234Qwer';
CREATE ROLE
postgres=#
小结
AI确实可以辅助我们提高工作效率,我们这里是一个极其简单的demo,当然对于复杂的业务逻辑来说AI目前不一定能够很好的实现。
不过已经能够预感到等后续发展到一定程度后,对部分工作种类来说可能会产生“革命性”的影响。