Python连接MySQL必须通过os.getenv("MYSQL_PASSWORD")动态获取密码,严禁硬编码或明文存于my.cnf/App.config;需校验环境变量非空、GRANT语句参数白名单过滤,并指定charset与auth_plugin。

password 参数绝不能出现在 Python 的 connect() 调用里,也不能写进 my.cnf 明文字段或 Unity 的 App.config 字符串中。这不是“建议”,而是上线前必须切断的泄露路径。
Python 连接 MySQL 时怎么安全传密码?
核心原则:密码必须脱离代码和配置文件,由运行时注入。
- 用
os.getenv("MYSQL_PASSWORD")获取,而不是写死password="123456" - 环境变量需提前设置:
export MYSQL_PASSWORD="xxx"(Linux/macOS)或$env:MYSQL_PASSWORD="xxx"(PowerShell) - 加兜底逻辑:
os.getenv("MYSQL_PASSWORD", "fallback")不推荐——fallback 仍是明文,应直接抛异常或拒绝启动 - 若用
pymysql,记得加charset="utf8mb4";若用mysql-connector-python,显式指定auth_plugin="caching_sha2_password",否则可能报Authentication plugin 'caching_sha2_password' cannot be loaded
MySQL 命令行连接怎么避免 -p 后明文输密码?
命令行输密码会留在 shell 历史、进程列表(ps aux)、系统日志里,风险极高。
- 优先用
mysql_config_editor:执行mysql_config_editor set --login-path=prod --host=localhost --user=app_rw --password,它会加密存到~/.mylogin.cnf - 后续连接必须显式带参数:
mysql --login-path=prod,不加--login-path就不会读这个文件 -
chmod 600 ~/.mylogin.cnf必须手动执行——该文件不会自动设权限,权限宽松等于白加密 - 别用
.my.cnf明文方案:[client] password=xxx是反模式,哪怕 chmod 600 也挡不住内存 dump 或调试器抓取
Unity 或桌面应用里如何管理连接字符串?
硬编码在 C# 脚本里等于把数据库钥匙打包进安装包,反编译几秒就能拿到。
- 用
App.config或appsettings.json存连接字符串,但password=xxx字段仍属明文 —— 必须配合构建时密钥注入或运行时解密 - 更稳妥做法:启动时从系统级凭据库读取,Windows 用
Credential Manager,macOS 用Keychain,Linux 用libsecret - Unity 中禁止用
PlayerPrefs.SetString("db_pass", ...)—— 它是纯文本存储,毫无防护 - 如果必须用配置文件,至少把密码字段 AES 加密,密钥存在环境变量或启动参数里,不要写死在代码中
GRANT 语句里拼接用户名为什么危险?
GRANT 不支持参数化,但用 Python 字符串格式化拼接用户/库名,等于亲手打开 SQL 注入后门。
- 错误示例:
cursor.execute(f"GRANT SELECT ON {db_name}.* TO '{user}'@'{host}'") - 攻击者注册用户名为
admin'@'%' IDENTIFIED BY 'x'; DROP USER 'root'@'%'; --,就能绕过校验删 root - 正确做法:对
user、host、db_name做白名单校验,只允许字母、数字、下划线,长度限制在 32 字符内 - 或者用 MySQL 8.0+ 的角色(ROLE)机制,把权限预定义好,运行时只分配角色名,不拼 SQL
真正容易被忽略的不是“怎么加密码”,而是“谁有权读密码”。~/.mylogin.cnf 权限错、os.getenv() 没校验返回值、GRANT 语句没过滤输入——这些细节一漏,前面所有加密和隔离都归零。


















