Skip to content

MySQL - 创建用户

正确的用户管理是数据库安全的基础。您应该为应用程序和管理员创建专用的用户账户,每个账户都拥有执行其任务所需的最小权限,而不是为所有操作都使用单个高权限账户(如 root)。

CREATE USER 语句在 MySQL 中创建一个新账户。要运行它,您必须以具有 CREATE USER 权限的用户(例如 root)身份登录。

CREATE USER [IF NOT EXISTS] 'username'@'hostname'
IDENTIFIED BY 'password';
  • username:新用户的名称。
  • hostname:允许用户连接的主机。常见值有 'localhost'(用于本地连接)或 IP 地址。使用 '%' 是一个通配符,允许从任何主机连接,但这应该极其谨慎地使用。
  • IF NOT EXISTS:一个可选子句,如果用户已存在则防止报错。

自 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';

新创建的用户没有任何权限。您必须使用 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;

您可以在创建用户时强制执行密码安全策略。此示例创建一个用户,其密码每 90 天过期一次,并且在 5 次登录失败后将被锁定 1 天。

CREATE USER 'secure_user'@'localhost'
IDENTIFIED BY 'MyPassword123!'
PASSWORD EXPIRE INTERVAL 90 DAY
FAILED_LOGIN_ATTEMPTS 5 PASSWORD_LOCK_TIME 1;

您可以查看存在哪些用户以及他们可以从何处连接:

SELECT user, host FROM mysql.user;

要查看特定用户的权限:

SHOW GRANTS FOR 'app_user'@'localhost';

在部署脚本中自动化用户创建是很常见的。这里有一个在 Python 中安全实现的方法。

import mysql.connector
from 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')