PostgreSQL 认证方式详解

PostgreSQL提供多种不同的客户端认证方式。被用来认证一个特定客户端连接的方法可以基于(客户端)主机地址、数据库和用户来选择。这里我们介绍一些常用的认证方式。

1、PostgreSQL如何完成用户认证?

一般当我们安装完PostgreSQL时可以发现,系统为我们创建好了一个名为Postgres的用户和一个名为Postgres的数据库。

我们想要使用这个Postgres用户去连接Postgres数据库时,只需要执行:

pg13@cnndr4pptliot-> psql
psql (13beta3)
Type "help" for help.

postgres=#

但是,当你执行完"psql"这个命令顺利地连接到数据库后,你有没有想过为什么我们没输入密码就直接连接进去了?Postgres这个用户的密码是什么呢?

第二个问题的答案很简单,就是Postgres用户默认是没有密码的,所以我们可以为它去设置个密码:

postgres=# \password
Enter new password:
Enter it again:
postgres=#

那么第一个问题,为什么我们不用输入密码就连到数据库里面了呢?那样不是会很不安全吗?这也就是和我们要介绍的PostgreSQL的用户认证方式有关了。
我们用过$PGDATA目录下的pg_hba.conf文件来设置用户认证的方式,这里我们来介绍一些常用的认证方式:

2、PostgreSQL认证方式

2.1、Peer认证

Peer 认证方法通过从内核获得客户端的操作系统用户名并把它用作被允许的数据库用户名(和可选的用户名映射)来工作。这种方法只在本地连接上支持。

例如这里我的pg数据库是安装在pg13这个用户下面的,那么当我使用peer认证方式时,将无法连接到postgres用户。

pg13@cnndr4pptliot-> psql -U postgres
psql: error: could not connect to server: FATAL:  Peer authentication failed for user "postgres"

要解决这个问题,我们必须将操作系统用户名映射到数据库用户。

修改pg_ident.conf文件:

# MAPNAME       SYSTEM-USERNAME         PG-USERNAME
  postgres-testing        pg13           postgres

修改pg_hba.conf文件:

# TYPE  DATABASE        USER            ADDRESS     METHOD

# "local" is for Unix domain socket connections only
local   all             all                  peer map=postgres-testing

重新加载配置然后连接:

pg13@cnndr4pptliot-> pg_ctl reload
server signaled

pg13@cnndr4pptliot-> psql -U postgres
psql (13beta3)
Type "help" for help.

postgres=# 

2.2、Trust认证

顾名思义,当trust认证被指定时,PostgreSQL假设任何可以连接到服务器的人都被授权使用他们指定的任何数据库用户名(即使是超级用户)访问数据库。当然,在database和 user列中设置的限制仍然适用。只有当在操作系统层对进入服务器的连接有足够保护时,才应该使用这种方法。

例如:

# TYPE  DATABASE        USER            ADDRESS     METHOD

# "local" is for Unix domain socket connections only
local   all             all                          trust

无需输入密码直接连接:

pg13@cnndr4pptliot-> psql bill bill
psql (13beta3)
Type "help" for help.

bill=#

2.3、Md5认证

md5认证是口令认证的一种,常见的还有:scram-sha-256和password认证。但是这里需要注意不推荐使用password认证的方式,因为这是将密码以明文的方式进行传输,所以一般都是使用md5的口令认证方式。

pg_hba.conf:

local  all              all                     md5

连接:

pg13@cnndr4pptliot-> psql bill bill
Password for user bill:
psql (13beta3)
Type "help" for help.

bill=#

这里需要注意md5认证方式的安全仍然存在一定的问题,因为我们创建用户时,密码将被加密存储在pg_catalog.pg_authid系统表中。

查看该表:

bill=# select * from pg_catalog.pg_authid where rolname = 'bill';
-[ RECORD 1 ]--+------------------------------------
oid            | 16384
rolname        | bill
rolsuper       | t
rolinherit     | t
rolcreaterole  | f
rolcreatedb    | f
rolcanlogin    | t
rolreplication | f
rolbypassrls   | f
rolconnlimit   | -1
rolpassword    | md5f9d79d4c823b3097f324f3ff2c3b497d
rolvaliduntil  |

可以看到rolpassword这一列存储了一串md5值,其加密算法md5(pwd+username),不可逆。
例如这里我的用户bill的密码为bill,那么可以得到:

bill=# select md5('billbill');
               md5
----------------------------------
 f9d79d4c823b3097f324f3ff2c3b497d
(1 row)

可以发现和pg_authid表中存储的值一样。如果被别人知道了用户的这个md5值,那么便会存在用户直接通过md5值连接的可能。

因为md5的认证流程大致为:

  1. 客户端发起认证消息。
  2. 服务端接收到认证消息报文,生成一个随机Salt,发生给客户端。
  3. 客户端收到Salt后,将计算这个值 md5(md5(pwd+username) + Salt) 得到认证秘钥,发送给服务端。
  4. 服务端收到客户端发过来的认证秘钥,与服务端存储的pg_catalog.pg_authid中对应的md5,计算md5(md5+Salt)得到一个值,与客户端发过来的认证秘钥对比,如果一致则认证成功,如果不一致则认证失败。

我们便可以通过修改源码的方式来直接利用md5值去连接数据库,详见:
src/interfaces/libpq/fe-auth.c

有兴趣的可以自己去研究下。

2.4、ident认证

ident 认证方法通过从一个 ident 服务器获得客户端的操作系统用户名并且用它作为被允许的数据库用户名(和可选的用户名映射)来工作。它只在 TCP/IP 连接上支持。

其使用方式类似与peer认证。

pg13@cnndr4pptliot-> psql -d postgres -U bill 
psql: FATAL:  Ident authentication failed for user "bill"

pg13@cnndr4pptliot-> psql -d postgres -U bill
psql: FATAL:  Peer authentication failed for user "bill"

pg13@cnndr4pptliot->$
[postgres@postgreshelp data]$ cat pg_hba.conf | grep ident
local  all              all             ident
host   all              all             ident
 

3、总结

一般情况下,我们需要根据实际的情况去选择用户认证方式,比较常用的就是trust或md5设置为默认身份验证方法。

如果担心md5的安全问题,可以选择使用scram-sha-256的认证方式(需要pg10以后的版本才支持)。

peer和ident方法更依赖于操作系统用户名,因此我们一般不使用这些身份验证方法。

参考链接:
http://www.postgres.cn/docs/12/client-authentication.html

https://postgreshelp.com/postgresql-user-authentication-demystified/#How_to_Change_a_Password_for_PostgreSQL_user

猜你喜欢

转载自blog.csdn.net/weixin_39540651/article/details/108866593
今日推荐