如何使用libpq的pgpass连接到PostgreSQL数据库而不需要指定明文密码?

11

Postgres的C库libpq文档介绍了一种更安全的方法来连接数据库,而不需要在源代码中指定密码。

我没有找到任何如何实现它的示例。如何让我的Postgre服务器使用这个文件?请帮忙。

4个回答

31

您不需要将它导入到您的Python程序中。使用.pgpass文件的目的在于它是一个受系统文件权限约束的普通文件,而像psycopg2这样的库所用到的libpq驱动程序将会在此文件中查找密码,而不是要求用户将密码写进源代码或者提示输入密码。

此外,该文件不是服务器端文件,而是客户端文件。所以,在*nix系统下,您应该有一个~/.pgpass文件,其中包含您想要连接的各种凭据信息。

针对OP评论的编辑:

为了让psycopg2通过.pgpass正确进行身份验证,需要完成两件主要事情:

  1. 在传递给psycopg2.connect的字符串中不要指定密码
  2. 确保已经为将通过psycopg2连接的用户添加了正确的条目到.pgpass文件中。

例如,如果要使其工作于本地主机 5432 端口上,所有数据库都可供特定用户使用,则应向该用户的.pgpass文件添加以下行:

localhost:5432:*:<username>:<password>

然后connect调用将采用以下形式:

conn = psycopg2.connect("host=localhost dbname=<dbname> user=<username>")

下层的libpq驱动程序会利用.pgpass文件获取密码,而psycopg2使用该驱动程序。


1
但是,psycopg2在Python程序中的连接应该长什么样子,才能让它查找~/.pgpass文件? - ovod
3
我需要补充一点,如果你在*nix操作系统上进行此操作,你还需要运行命令chmod 0600 ~/.pgpass。如果权限比这更少,文件将被忽略。按照khampson的回答执行此命令对我来说解决了问题。 - Corey Levinson
如果文件不在默认位置怎么办?passfile似乎无法找到它。 - thomi

0

补充@khampson的答案,我只能在Windows中添加PGPASSFILE环境变量(并随后重新启动pycharm),即使我的pgpass文件位于默认位置(%APPDATA%\postgresql\pgpass.conf),才能使其正常工作。


-1

好的。你要求 .pgpass 但是...

还有 "连接服务文件"

默认情况下,每个用户的服务文件名为 ~/.pg_service.conf。 可以通过设置环境变量 PGSERVICEFILE 来指定不同的文件名

请参考 https://www.postgresql.org/docs/15/libpq-pgservice.html

格式为 ".INI"。参数是连接参数。 例如:

# this is a comment in my service file
[a_service]
host=dbserver.loc
port=5432
dbname=thedbname
user=thebest
password=bho
application_name=ifyoulike

# Here is another service
[another_service]
host=etc
port=etc

通过psql访问:

psql service=a_service

通过psycopg2访问:

db = psycopg2.connect('service=a_service')

通过sqlalchemy访问:

eng = sqlalchemy.create_engine('postgresql:///?service=another_service')


-7
#!/usr/bin/python
import psycopg2
import sys
import pprint

def main():
    conn_string = "host='127.0.0.1' dbname='yourdatabsename'  user='yourusername' password='yourpassword'"
print "Connecting to database\n ->%s" % (conn_string)
conn = psycopg2.connect(conn_string)
cursor = conn.cursor()
cursor.execute("SELECT * FROM tablename")


records = cursor.fetchall()
pprint.pprint(records)

if __name__ == "__main__":
    main()

请考虑编辑您的帖子,添加更多关于代码的解释以及为什么它可以解决问题的说明。一个主要只包含代码(即使它是有效的)的答案通常不能帮助提问者理解他们的问题。 - Drenmi
1
问题明确指出密码不应在代码中指定,而这个例子恰恰相反。 - Saket

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接