MySQL - 创建用户
在 MySQL 中安全地管理用户
Section titled “在 MySQL 中安全地管理用户”正确的用户管理是数据库安全的基础。您应该为应用程序和管理员创建专用的用户账户,每个账户都拥有执行其任务所需的最小权限,而不是为所有操作都使用单个高权限账户(如 root)。
CREATE USER 语句
Section titled “CREATE USER 语句”CREATE USER 语句在 MySQL 中创建一个新账户。要运行它,您必须以具有 CREATE USER 权限的用户(例如 root)身份登录。
CREATE USER [IF NOT EXISTS] 'username'@'hostname'IDENTIFIED BY 'password';username:新用户的名称。hostname:允许用户连接的主机。常见值有'localhost'(用于本地连接)或 IP 地址。使用'%'是一个通配符,允许从任何主机连接,但这应该极其谨慎地使用。IF NOT EXISTS:一个可选子句,如果用户已存在则防止报错。
现代认证:caching_sha2_password
Section titled “现代认证:caching_sha2_password”自 MySQL 8.0 起,默认的认证插件是 caching_sha2_password,它比旧的 mysql_native_password 更安全。上述语法将使用此默认值。如果您需要支持不理解新插件的旧客户端,可以显式指定旧插件:
-- 为现代应用程序创建用户(推荐)CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'a_very_strong_password';
-- 为旧系统创建用户(仅在必要时使用)CREATE USER 'legacy_user'@'localhost'IDENTIFIED WITH mysql_native_password BY 'another_strong_password';授予权限:最小权限原则
Section titled “授予权限:最小权限原则”新创建的用户没有任何权限。您必须使用 GRANT 语句明确授予它们。最佳安全实践是最小权限原则(Principle of Least Privilege):只授予用户绝对需要的权限。
除非您正在创建一个真正的管理员账户,否则请避免使用 GRANT ALL PRIVILEGES ON *.*。对于应用程序用户而言,这会带来危险的过度授权。
示例:一个真实的应用程序用户
Section titled “示例:一个真实的应用程序用户”让我们授予 app_user 在 my_app_db 数据库中的表上读写数据(SELECT、INSERT、UPDATE、DELETE)的能力,但仅限于这些表。
GRANT SELECT, INSERT, UPDATE, DELETE ON `my_app_db`.* TO 'app_user'@'localhost';
-- 最好立即应用更改。FLUSH PRIVILEGES;高级用户管理
Section titled “高级用户管理”密码过期策略
Section titled “密码过期策略”您可以在创建用户时强制执行密码安全策略。此示例创建一个用户,其密码每 90 天过期一次,并且在 5 次登录失败后将被锁定 1 天。
CREATE USER 'secure_user'@'localhost'IDENTIFIED BY 'MyPassword123!'PASSWORD EXPIRE INTERVAL 90 DAYFAILED_LOGIN_ATTEMPTS 5 PASSWORD_LOCK_TIME 1;验证用户和权限
Section titled “验证用户和权限”您可以查看存在哪些用户以及他们可以从何处连接:
SELECT user, host FROM mysql.user;要查看特定用户的权限:
SHOW GRANTS FOR 'app_user'@'localhost';使用客户端程序创建用户
Section titled “使用客户端程序创建用户”在部署脚本中自动化用户创建是很常见的。这里有一个在 Python 中安全实现的方法。
Python 示例
Section titled “Python 示例”import mysql.connectorfrom mysql.connector import errorcode
def create_app_user(admin_config, new_user, new_pass, database): try: # 以管理员身份连接(例如 root) with mysql.connector.connect(**admin_config) as connection: with connection.cursor() as cursor: print(f"Creating user {new_user}...") # 使用 IF NOT EXISTS 来避免重复运行时报错 cursor.execute(f"CREATE USER IF NOT EXISTS '{new_user}'@'localhost' IDENTIFIED BY '{new_pass}'")
print(f"Granting privileges on {database}...") cursor.execute(f"GRANT SELECT, INSERT, UPDATE, DELETE ON `{database}`.* TO '{new_user}'@'localhost'")
cursor.execute("FLUSH PRIVILEGES") print("User created and privileges granted successfully.")
except mysql.connector.Error as err: print(f"Database Error: {err}")
# --- 用法 ---admin_credentials = { 'user': 'root', 'password': 'your_root_password', 'host': 'localhost'}
create_app_user(admin_credentials, 'api_user', 'super_secret_api_pass', 'my_app_db')