python Psycopg2:如何处理密码中的特殊字符?

gab6jxml  于 2023-09-29  发布在  Python
关注(0)|答案(3)|浏览(270)

我正在尝试连接到数据库示例,但我的密码包含以下特殊字符:反斜杠、加号、点、星号/星星和at符号。例如,12@34\56.78*90(正则表达式噩梦lol)
如何安全地将其传递给连接字符串?我的代码看起来像这样:

connection_string = f'user={user} password={pass} host={host} dbname={dbname} port={port}'

connection = psg2.connect(connection_string)

它给了我错误的通行证/用户名错误。然而,我直接在数据库上尝试了这个组合,它工作正常,我在Python代码上尝试了另一个组合,它也工作正常。所以看起来问题是密码被奇怪地传递到连接。
我试过urllib scape,我试过密码上的双引号,到目前为止都不起作用:(

gc0ot86w

gc0ot86w1#

尝试使用此代码来处理包含特殊字符的密码。

import psycopg2

# Replace these values with your actual database credentials
user = "your_username"
password = "12@34\\56.78*90"  # Note the double backslash to escape the backslash
host = "your_host"
dbname = "your_dbname"
port = "your_port"

# Escape the password and construct the connection string
escaped_password = password.replace("'", "''")  # Replace single quotes with double single quotes
connection_string = f"user={user} password='{escaped_password}' host={host} dbname={dbname} port={port}"

# Establish the database connection
connection = psycopg2.connect(connection_string)

# Now you can use the 'connection' object to interact with the database
ovfsdjhp

ovfsdjhp2#

基于一个reddit线程,我发现直接通过变量传递变量而不是连接字符串可以做到这一点:
con = psycopg2.connect(dbname=dn,user=du,password=dp,host=dh,port=dbp,)

ryevplcw

ryevplcw3#

正如jjanes在他们的评论中提到的,在这个特定的例子中,双反斜杠就足够了:

password = '12@34\\56.78*90'

因为您在脚本中硬编码了密码(只是为了测试,对吗?),你也可以使用一个原始字符串来自动转义反斜杠:

password = r'12@34\56.78*90'

嵌入的引号可以转义或替换(如Maimoona Abidanswer),但如果密码包含单引号,则使用双引号引用字符串可能更简单,反之亦然,或者使用三重引号:

password = r"12@34\56.78*9'0"
password = r'''12@34\56.78*9'0'''

PostgreSQL还支持从PGPASSWORD环境变量阅读密码,psycopg 2似乎直接支持这一点(尽管似乎没有文档)。如果定义了PGPASSWORD,则不必将password传递到psycopg2.connect()
如果密码存储在环境中,则必须根据shell的引用规则对其进行转义,例如在bash中:

PGPASSWORD='12@34\56.78*9'\''0' python myscript.py

PostgreSQL还支持将密码存储在一个文件中,默认情况下在${HOME}/.pgpass中,但可以由env var PGPASSFILE定义。Psycopg 2并不直接支持这一点,但您可以在代码中读取该文件:如果存储在文件中,则不需要转义(但在阅读时不要忘记删除行结束字符):

$ cat .pgpass
localhost:5432:test:souser:12@34\56.78*9'0
PGPASSFILE=path/to/.pgpass python myscript.py

PostgreSQL还支持使用URI进行连接。在这种情况下,密码可能需要进行百分比编码:

from urllib import parse
import psycopg2

dsn = fr'postgresql://souser:{parse.quote(password)}@localhost/test'

with psycopg2.connect(dsn=dsn) as conn:
    ...

上述所有方法也适用于psycopg.connect()
测试脚本示例:

import os
import psycopg2

if os.getenv('PGPASSWORD'):
    # psycopg22 will use the env var automatically, no need to specify it here.
    password = None
elif password_file := os.getenv('PGPASSFILE'):
    with open(password_file) as f:
        line = next(f)
        *_, password = line.rpartition(':')
        password = password.strip()
else:
    password = r"12@34\56.78*9'0"

conn_data = dict(user='souser', dbname='test', host='localhost', port=5432)
if password is not None:
    conn_data['password'] = password

with psycopg2.connect(**conn_data) as conn:
    with conn.cursor() as cur:
        cur.execute("""SELECT 1 WHERE 1 = 2""")
        assert cur.fetchone() is None
conn.close()

相关问题