Skip to content

MySQL - 删除用户

安全的用户管理:删除 MySQL 用户

Section titled “安全的用户管理:删除 MySQL 用户”

管理用户账户是任何数据库管理员的关键安全功能。DROP USER 语句用于永久从 MySQL 中移除用户账户,撤销其所有访问权限和特权。此操作不可逆,对于维护安全的数据库环境至关重要。

要执行 DROP USER,你必须拥有全局 CREATE USER (创建用户) 权限或 mysql 系统数据库上的 DELETE (删除) 权限。当用户被删除时,其账户和所有相关的权限记录都将被移除。

完整语法指定了用户名和用户可以连接的主机名。

DROP USER [IF EXISTS] 'username'@'hostname';

用户由其名称和主机名共同定义。'user'@'localhost' 与 'user'@'192.168.1.100' 或 'user'@'%' 是不同的用户。

首先,让我们创建一个临时用户进行演示。

CREATE USER 'temp_app_user'@'localhost' IDENTIFIED BY 'a_secure_password';

你可以通过查询 mysql.user 表来验证用户是否存在:

SELECT user, host FROM mysql.user WHERE user = 'temp_app_user';

现在,让我们删除这个用户。

DROP USER 'temp_app_user'@'localhost';

再次查询 mysql.user 表将显示用户已被移除。

你可以在一个命令中通过列出多个用户账户并用逗号分隔它们来删除它们。这对于清理脚本来说效率很高。

让我们创建另外两个临时用户。

CREATE USER 'user1'@'localhost';
CREATE USER 'user2'@'localhost';

现在同时删除这两个用户:

DROP USER 'user1'@'localhost', 'user2'@'localhost';

注意:DROP ROLE 是一个不同的命令,用于移除角色(权限的集合),而不是用户账户。原始教程错误地混淆了这些概念。

尝试删除一个不存在的用户会导致错误,这可能会阻止自动化脚本的运行。使用 IF EXISTS 子句可以使你的命令具有幂等性 (idempotent) —— 它确保用户被删除,即使他们已经被移除也不会失败。

DROP USER 'no_such_user'@'localhost';

这将产生一个错误:

ERROR 1396 (HY000): Operation DROP USER failed for 'no_such_user'@'localhost'
DROP USER IF EXISTS 'no_such_user'@'localhost';

此命令成功完成并带有警告,允许脚本继续执行。

Query OK, 0 rows affected, 1 warning (0.00 sec)

安全警告: 应用程序代码几乎不应拥有删除用户的权限。此功能应限于安全的、由管理员运行的脚本,用于环境的配置或解除配置。

NodeJS
Python
PHP
Java
// 此脚本仅供管理员使用,不适用于 Web 应用程序。
const mysql = require('mysql2/promise');
async function deprovisionUser(username, hostname) {
// 使用具有特权的账户运行此脚本。
const adminConn = await mysql.createConnection({ /* 管理员用户配置 */ });
try {
console.log(`正在删除用户 '${username}'@'${hostname}'...`);
// 对于 DDL 标识符,无法使用预处理语句,
// 因此请确保输入经过验证并来自受信任的来源。
await adminConn.query(`DROP USER IF EXISTS ?@?`, [username, hostname]);
console.log('用户删除成功。');
} catch (error) {
console.error('删除用户失败:', error);
} finally {
await adminConn.end();
}
}
// 用法:
deprovisionUser('legacy_service_account', '10.0.1.5');
# 用于用户清理的管理员 Python 脚本。
import mysql.connector
def drop_mysql_user(config, username, hostname):
try:
with mysql.connector.connect(**config) as conn:
with conn.cursor() as cursor:
print(f"正在删除用户 '{username}'@'{hostname}'...")
# 为安全起见,使用参数替换
cursor.execute("DROP USER IF EXISTS %s@%s", (username, hostname))
print("用户删除成功。")
except mysql.connector.Error as err:
print(f"错误: {err}")
# 管理员连接配置
admin_config = {'user': 'admin_user', 'password': 'admin_pass', 'host': '127.0.0.1'}
drop_mysql_user(admin_config, 'test_user', 'localhost')
// 用于服务器维护的 PHP 脚本。
$adminPdo = new PDO(/* 管理员 DSN */);
$adminPdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
function dropUser(PDO $pdo, string $user, string $host)
{
try {
// 为安全起见使用占位符
$stmt = $pdo->prepare("DROP USER IF EXISTS ?@?");
$stmt->execute([$user, $host]);
echo "用户 {$user}@{$host} 删除成功。\n";
} catch (PDOException $e) {
echo "删除用户错误: " . $e->getMessage() . "\n";
}
}
dropUser($adminPdo, 'old_report_user', '%');
// 用于管理工具的 Java 实用程序。
public void dropUser(String username, String hostname) {
String sql = "DROP USER IF EXISTS ?@?";
// 使用管理员连接
try (Connection conn = getAdminConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, username);
pstmt.setString(2, hostname);
pstmt.executeUpdate();
System.out.printf("用户 '%s'@'%s' 删除成功。%n", username, hostname);
} catch (SQLException e) {
e.printStackTrace();
}
}