使用psycopg2连接到数据库而无需密码

53

我在本地主机上有一个Postgres数据库,可以不需要密码访问。

$ psql -d mwt
psql (8.4.12)
Type "help" for help.

mwt=# SELECT * from vatid;
  id   | requester_vatid |...
  -----+-----------------|...   
  1719 | IT00766780266   |...

我想从Django访问那个数据库,所以我放入了DATABASES

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'mwt',
        'USER': 'shaoran',
        'HOST': 'localhost'
    }
}

由于我不需要密码来访问我的测试数据库,所以在设置中没有提供任何PASSWORD值。

$ ./manage.py shell
>>> from polls.models import Vatid
>>> Vatid.objects.all()
  connection_factory=connection_factory, async=async)
  OperationalError: fe_sendauth: no password supplied

我尝试使用 PASSWORD: '' 但是出现了相同的错误信息。我也尝试使用 PASSWORD: None 但是并没有帮助。

我一直在查找关于这个问题的 Django 文档,但是我找不到有用的信息。是否可以配置 django.db.backends.postgresql_psycopg2 来接受空密码?


您可以通过localhost或Unix域套接字进行配置。这里解释了两种情况的工作原理。 - j-i-l
@jojo 感谢您的评论。这么久以前的事情我都不记得我当时是怎么修复它的了,而且这个项目也已经很久没有维护了。 - Pablo
希望这对其他人有所帮助!与提到的项目相反,这种配置仍然存在潜在的陷阱,这两个事实都是不幸的。 - j-i-l
@jojo 根据所有答案和问题的赞数,这个问题肯定也帮助了其他人。现在我记起来了,问题就在于(正如你在回答中所述),我使用了 HOST 参数。 - Pablo
5个回答

72

令人惊讶的是,答案是根本不指定主机。如果您这样做,

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'mwt',
    }
}

然后,psycopg2将使用与psql相同的方式使用Unix套接字进行连接。 当您指定HOST时,psycopg2将使用TCP/IP进行连接,这需要密码。


1
仍然无法成功:django.db.utils.OperationalError: FATAL: Peer authentication failed for user "www-data";必须在hba.conf中添加local all www-data trust,并放在默认的local all postgres peer行之前。 - jcomeau_ictx
1
@jcomeau_ictx 我通过Unix域(如此答案隐含地建议)以及像被接受的答案所建议的localhost,添加了一个完整的解释来说明这个工作原理。 - j-i-l
在将postgres设置为信任后,我可以使用PGAdmin登录,但Django仍无法建立连接并出现了fe_authentication错误。只有这个解决方案起作用!谢谢! - ratulotron

30
为了避免在 Django 的 `settings.py` 中使用密码,请将 `pg_hba.conf` 中下面这行中的 `md5` 改为 `trust`:
``` md5 ```
host    all             all             127.0.0.1/32            trust

想要深入了解postgres安全配置,请阅读这篇文档。

定位该文件的方法:

sudo -u postgres psql -c 'SHOW hba_file;'

13

检查您的pg_hba.conf文件,允许用户shaoran通过localhost进行连接,然后在Django设置中提供shaoran的密码或在pg_hba.conf中信任该用户。

您可以通过psql -d mwt连接,这是因为psql使用了一些默认的连接值,并且这些默认值在pg_hba.conf中被设置为信任。例如,在我的机器上,默认主机是本地socket而不是localhost


@Pablo 这里的关键是你指定了 host=localhostuser=shaoran,这可能与 psqlRails 使用的 DSN 不同。 - okm
哎呀,我没意识到代码块在评论框中无法使用。不管怎样,我犯了一个大错误,因为我的当前用户@工作是yanez而不是shaoran(我的家庭用户)。我将USER更改为“yanez”,但仍然收到相同的错误。我甚至从settings.py中删除了USER条目,以使配置与rails的配置匹配,但仍然出现错误:( - Pablo
@Pablo 我不知道Rails如何处理这个问题,Django有自己的默认设置。详情请见:https://docs.djangoproject.com/en/dev/ref/settings/#databases - okm
1
感谢您的帮助。除了错误的用户名之外,这里的问题是“主机”条目。我认为如果没有它,psql、rails和psycopg2将通过文件套接字而不是网络套接字访问本地数据库。 - Pablo
@radtek 你可能在 psqlpsycopg2 中有不同的设置:在 shell 中检查 psql --help 的输出中的 Connection options 部分;在 Python shell 中检查 psycopg2 connection 对象的 dsn 属性。 - okm
显示剩余3条评论

8
作为一个面临同样问题并且只有在结合这里提供的答案和谷歌搜索后才找到解决方案的人,我决定整理一篇完整的答案。
首先需要注意的是:在`settings.py`中放置或省略`'HOST'`都是可行的选项。然而,无论是放置还是省略`'HOST'`都会影响如何设置postgresql配置。
joerick的答案那样省略`'HOST'`会导致psycopg2尝试通过Unix域套接字连接。另一方面,如果您的配置包含`'HOST'`键,则psycopg2将尝试通过IPv4/6`localhost`连接。这将产生很大的差异,因为postgresql身份验证配置(`/etc/postgresql/x.x/main/pg_hba.conf`)是针对这两种连接方式之一的。
带回家的信息:
请确保选择与您在postgresql身份验证配置中配置的连接类型相同的连接类型。
第二个需要注意的事情: postgresql认证配置(/etc/postgresql/x.x/main/pg_hba.conf)关注条目的顺序。

文档实际上非常清楚,(但我仍然会掉进local all all peer的陷阱):

第一个匹配连接类型、客户端地址、请求的数据库和用户名的记录用于执行身份验证。没有“回退”或“备份”:如果选择了一条记录并且身份验证失败,则不考虑后续记录。如果没有记录匹配,则拒绝访问。

要点:

确保任何具体规则在更广泛的规则之前。


现在我们已经了解了所有这些,以下是如何在没有密码的情况下访问,一次使用'HOST'(因此通过localhost),一次不使用(因此通过Unix套接字)

在本地连接

在你的settings.py的数据库配置中指定'HOST': 'localhost':

# ...
'HOST': 'localhost',
# ...

'PASSWORD' 不需要,可以省略。

您需要在postgresql身份验证配置(/etc/postgresql/x.x/main/pg_hba.conf)中设置的规则是 host 类型。

注意规则的顺序。因此,如果您有一个名为'my_user'的用户应该能够无需密码访问数据库'my_database',正确的配置如下:

# RIGHT WAY...
host my_database my_user 127.0.0.1/32 trust
host my_database my_user ::1/128 trust
# ...
host all all 127.0.0.1/32 peer
# ...

反转顺序将导致“未提供密码”错误。

通过Unix域套接字连接

不要在您的设置中放置'HOST'键。也不需要'PASSWORD'

在postgresql身份验证配置中,通过Unix域套接字访问是使用类型为local的规则进行管理的。

如果'my_user'应该获得对数据库'my_database'的受信任(无需密码)访问权限,则需要像这样的一行:

local my_database my_user trust

关于在哪里放置这行代码,规则是需要将其放置在与 DATABASEUSER 相关的任何更广泛规则之前。为了安全起见,我建议将其放置在 /etc/postgresql/x.x/main/pg_hba.conf开头。如果您的pg_hba.conf文件如下:

# RIGHT WAY...
local my_database my_user trust
# ...
local all all peer
# ...

你可以无需密码即可开始使用。但如果出现以下情况:
# WRONG WAY! ...
local all all peer
# ...
local my_database my_user trust
# ...

您需要提供密码。


最后提示:

在修改/etc/postgresql/x.x/pg_hba.conf后不要忘记重新启动PostgreSQL服务

sudo service postgresql restart

 

希望这对你有所帮助。编程愉快!


2

我只与“local all all peer”一起生活。连接字符串应该没有主机、用户和密码: postgres:///mydbname。

如果没有environ模块,它看起来是这样的:

DATABASES = {
    'default': {'NAME': 'mydatabase', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', 'ENGINE': 'django.db.backends.postgresql_psycopg2'}
}

使用environ模块:
import environ
env = environ.Env()
DATABASES = {
    'default': env.db('DATABASE_URL', default='postgres:///mydatabase'),
}

如果 .env 文件中没有 DATABASE_URL 设置,则需要进行设置。

仅对于用户 'postgres',我使用 md5,但仅限于从 psql/pgadmin3 中使用,而不是从 Django 代码中使用。

# /etc/postgresql/version/cluster/pg_hba.conf:
local all postgres md5
local all all peer

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