在PostgreSQL中,用户密码是否有限制?
这篇文章是2021年PostgreSQL圣诞日历的第15天的文章。
这个话题与标题一样,询问了关于设置PostgreSQL登录用户密码时是否存在最小字符数、最大字符数以及可使用字符种类等限制。
我参加了第18届PostgreSQL非会议,并在同一个主题上发表了演讲,但是我突然想起来我没有把这篇文章整理成一篇,而且还有圣诞节日历,这是一个很好的机会,所以我决定整理一下。
顺便提一下,这里是在Ankan Conference上的演讲资料。
追寻PostgreSQL密码的谜团!
结论
总的来说,PostgreSQL用户的密码实际上没有限制。然而,使用多字节字符或者异常长的字符串等过于奇特的密码是不实用的。请使用常见的字符类型和字符数量来设置密码。
为什么选择以这个主题写文章。
我正在进行PostgreSQL的安装和设计工作,当创建用户时,我会询问客户:“您希望如何设置密码?如果您有项目中使用的规则,请告诉我。”大多数情况下,项目会有统一的密码规则,但有时规则尚未确定,反而会被问到“请告诉我在PostgreSQL中可用的密码字符和长度是多少”。
现在遇到了困难。由于用户可以创建任何类型的密码,因此我从未关注过密码限制。在MySQL中可以设置密码策略。
虽然可以说“没有限制”,但没有依据。基于“以前任何密码都可以”的理由有些薄弱。既然如此,我决定调查一下密码限制。
我在网上试着搜索一下
尝试使用关键字「PostgreSQL 密码限制」等搜索,虽然能找到有关使用PostgreSQL作为数据库工具时的密码限制,但尚未找到有关PostgreSQL本身密码限制的描述的网站。(此言仅指在未经论证的情况下发表时。)
尝试阅读手册
PostgreSQL的日本语手册因为热心志愿者的翻译而变得更加完善(非常感谢)。我查阅了涉及用户密码的命令,如CREATE ROLE和ALTER ROLE,但很遗憾,并没有关于密码限制的任何说明。
直觉上来考虑,如果密码有限制的话,应该在手册中有记载。如果没有这样的记载,难道是说明没有限制吗?
不过,真的会发生这种事情吗?
我读读这个来源。
我决定阅读最可靠的文献来源。
然而,PostgreSQL是用C语言编写的程序。很遗憾,笔者没有C语言编程经验。尽管如此,我决定读一部分可能能够理解的内容,而不是全部。这就是能够直接查阅源代码的开源软件PostgreSQL的优点。
下载和解压源代码。
请从以下的URL下载源代码。
如果您有适用的版本,请从该文件夹中下载最新版本14.1的源代码。

可能由于版本的不同存在差异,但源代码应该以tar.bz2或tar.gz的形式进行压缩。如您使用Windows操作系统,请使用相应的解压工具进行解压缩。这两种压缩文件的内容是相同的。

展开后,会解压出以下的文件夹和文件。PostgreSQL的源代码存储在src文件夹中。

尽管src文件夹的内容很复杂,一眼看上去无法确定每个东西在哪里。
关于详细文件夹的说明,我将交给其他人,但请记住backend文件夹的内容是PostgreSQL服务器端核心的一部分。这次要确认的与用户密码相关的源代码也在其中。

调查与用户相关的来源
在backend/commands文件夹中,记录着与用户创建和修改相关的源代码,它们被写在名为user.c的源文件中。
跟踪其中的CreateRole函数,看看是否存在与密码相关的记录。
CreateRole函数首先声明了变量。在这个阶段,密码的限制还没有关系。
然后检查执行CREATE ROLE时的选项组合以及指定选项是否具有执行权限,如果不能执行,则返回错误消息。
在这个阶段,仅检查选项,不检查密码本身。
当各种检查完成后,会引用名为check_password_hook的变量,并出现一个类似进行密码检查的if语句。

「哦!果然在进行某种检查!」我想到,但是check_password_hook变量是在user.c的开头声明的变量,并且初始化为NULL,并且至今没有将其赋予不同的值的行。也就是说,通常情况下,这个if语句是不会执行的。最终并没有进行密码检查。
接下来的操作是向名为pg_authid的系统目录中添加记录,该目录用于存储与用户和角色相关的信息,但不会进行密码检查,一直到最后。
真的没有限制吗?
你真的没有检查密码吗?真的无所谓吗?我试着试一下。
多字节字符密码
我尝试执行了以下SQL语句。
CREATE ROLE multibyte_user LOGIN PASSWORD 'パスワードはマルチバイトで';
可以很好地由用户自己创建。

长密码
我尝试使用1024个字符创建用户的密码。

看起来只要在SQL中将其作为字符串处理,就可以没有什么特别的问题来创建。
再重申一次
在使用PostgreSQL的用户密码时,实际上没有太多限制。然而,使用包含多字节字符或者过长字符的密码是不实用的。输入这样的密码非常困难,有些环境可能根本不接受输入。
例如,在输入密码以操作PostgreSQL的工具时,很可能无法输入多字节字符。反过来说,为了适应使用PostgreSQL的软件或工具的限制,可以认为PostgreSQL本身没有特别的限制。
建议使用常见的字符类型和长度的密码。
填补
最后补充一点。
检查密码钩子
在user.c中提到的check_password_hook是什么东西?
在PostgreSQL中,有一个称为hook的机制,可以将自定义的处理程序插入到PostgreSQL处理过程中的特定位置。hook有一个固定的位置,check_password_hook也是其中之一。
虽然不能轻松地在片刻之间创建,但如果有一个可以限制密码并灵活指定密码条件的扩展功能可能会很方便。
pg_authid: 用户在PostgreSQL中的身份标识
pg_authid是存储用户和角色信息的系统目录。通过CREATE ROLE命令创建的角色将存储在该表中。
pg_authid的rolpassword列是用于存储密码的列,其数据类型为text。
text类型的最大长度为1GB,因此人们可能认为密码的上限也是1GB。然而,当通过CREATE ROLE或ALTER ROLE创建用户时,通常会将经过md5或SCRAM-SHA-256哈希处理的值存储在rolpassword列中。
由于md5和SCRAM-SHA-256都有确定的位数限制,因此不可能达到1GB。
因此,在通常操作范围内,可以认为密码没有实际限制。