Skip to content

MySQL - 显示权限

在 MySQL 中,一个健壮的安全模型控制着用户可以执行的操作。访问通过一套权限系统进行管理。用户必须被授予适当的权限才能执行诸如选择数据、创建表或管理服务器等操作。

使用 SHOW PRIVILEGES 列出所有可用权限

Section titled “使用 SHOW PRIVILEGES 列出所有可用权限”

SHOW PRIVILEGES 语句显示 MySQL 服务器支持的所有系统权限的完整列表。这有助于了解您可以授予用户的全部权限范围。

输出包含三列:

  • Privilege: 权限名称(例如,SELECT、CREATE USER)。
  • Context: 权限适用的级别(例如,表、服务器管理、函数)。
  • Comment: 权限的简要说明。
SHOW PRIVILEGES;

执行此查询将列出您的 MySQL 服务器版本支持的所有权限。

SHOW PRIVILEGES;

输出将是一个很长的系统权限列表。以下是来自现代 MySQL 8.x 服务器的一小部分示例:

PrivilegeContextComment
AlterTables修改表
Create userServer Admin创建新用户
DeleteTables删除现有行
DropDatabases, Tables, Views删除数据库、表和视图
ExecuteFunctions, Procedures执行存储例程
InsertTables向表中插入数据
SelectTables从表中检索行
UpdateTables更新现有行
REPLICATION_SLAVE_ADMINServer Admin执行复制管理

使用 SHOW GRANTS 检查特定用户的授权

Section titled “使用 SHOW GRANTS 检查特定用户的授权”

更常见的情况是,您会想查看已授予特定用户的具体权限。为此,SHOW GRANTS 命令是正确的工具。

SHOW GRANTS FOR 'username'@'hostname';

让我们检查连接自任何主机 (%) 的用户 app_user 的权限。

SHOW GRANTS FOR 'app_user'@'%';
+-------------------------------------------------------------------------+
| Grants for app_user@% |
+-------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `app_user`@`%` |
| GRANT SELECT, INSERT, UPDATE ON `my_app_db`.* TO `app_user`@`%` |
+-------------------------------------------------------------------------+

此输出清楚地表明 app_user 具有基本连接权限 (USAGE),并且可以对 my_app_db 数据库中的所有表执行 SELECT、INSERT 和 UPDATE 操作。

您也可以从应用程序代码中执行 SHOW GRANTS 以验证权限。以下是几种语言中的现代、安全示例。

切勿在源代码中硬编码数据库凭据。使用环境变量(例如,从 .env 文件加载)来存储敏感信息,如用户名和密码。

Python
Node.js
PHP
Java
此示例使用 `mysql-connector-python` 库和 `with` 语句进行自动资源管理。
**设置:** `pip install mysql-connector-python python-dotenv`
```python
import mysql.connector
import os
from dotenv import load_dotenv
load_dotenv() # Load variables from .env file
# --- 从环境变量配置 ---
db_config = {
'host': os.getenv('DB_HOST'),
'user': os.getenv('DB_USER'),
'password': os.getenv('DB_PASSWORD'),
}
user_to_check = 'app_user'
host_to_check = '%'
try:
# Use a 'with' statement for automatic connection closing
with mysql.connector.connect(**db_config) as connection:
with connection.cursor() as cursor:
query = "SHOW GRANTS FOR %s@%s"
cursor.execute(query, (user_to_check, host_to_check))
print(f"Privileges for {user_to_check}@{host_to_check}:")
for grant in cursor:
print(grant[0])
except mysql.connector.Error as e:
print(f"Error connecting to MySQL: {e}")

此示例使用 mysql2/promise 库和 async/await 来编写现代异步代码。

设置: npm install mysql2 dotenv

const mysql = require('mysql2/promise');
require('dotenv').config(); // Load variables from .env file
// --- 从环境变量配置 ---
const dbConfig = {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
};
const userToCheck = 'app_user';
const hostToCheck = '%';
async function checkGrants() {
let connection;
try {
connection = await mysql.createConnection(dbConfig);
const query = 'SHOW GRANTS FOR ?@?';
const [rows] = await connection.execute(query, [userToCheck, hostToCheck]);
console.log(`Privileges for ${userToCheck}@${hostToCheck}:`);
rows.forEach(row => {
console.log(Object.values(row)[0]);
});
} catch (error) {
console.error(`Error connecting to or querying MySQL: ${error.message}`);
} finally {
if (connection) {
await connection.end();
}
}
}
checkGrants();

此示例使用现代 mysqli 扩展,采用面向对象风格并包含错误处理。

设置: 使用 Composer 管理依赖。

<?php
// Use Composer's autoloader for libraries like a .env loader
// require 'vendor/autoload.php';
// $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
// $dotenv->load();
// --- 配置(最好来自环境变量)---
$dbHost = getenv('DB_HOST');
$dbUser = getenv('DB_USER');
$dbPassword = getenv('DB_PASSWORD');
$userToCheck = 'app_user';
$hostToCheck = '%';
// Enable exception reporting for mysqli
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$mysqli = new mysqli($dbHost, $dbUser, $dbPassword);
// Use prepared statements even for SHOW GRANTS to be safe
$stmt = $mysqli->prepare("SHOW GRANTS FOR ?@?");
$stmt->bind_param("ss", $userToCheck, $hostToCheck);
$stmt->execute();
$result = $stmt->get_result();
echo "Privileges for {$userToCheck}@{$hostToCheck}:\n";
while ($row = $result->fetch_array()) {
echo $row[0] . "\n";
}
$stmt->close();
$mysqli->close();
} catch (mysqli_sql_exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>

此示例使用现代 JDBC,带有 try-with-resources 语句用于自动资源管理,并使用了 PreparedStatement。

设置: 使用 Maven 或 Gradle 等构建工具来包含 MySQL JDBC 驱动依赖。

import java.sql.*;
public class ShowGrantsExample {
public static void main(String[] args) {
// --- 配置(最好来自属性文件或环境变量)---
String url = "jdbc:mysql://" + System.getenv("DB_HOST") + ":3306/";
String user = System.getenv("DB_USER");
String password = System.getenv("DB_PASSWORD");
String userToCheck = "app_user";
String hostToCheck = "%";
String sql = "SHOW GRANTS FOR ?@?";
// Use try-with-resources for automatic closing of Connection, PreparedStatement, and ResultSet
try (Connection conn = DriverManager.getConnection(url, user, password);
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, userToCheck);
pstmt.setString(2, hostToCheck);
try (ResultSet rs = pstmt.executeQuery()) {
System.out.printf("Privileges for %s@%s:%n", userToCheck, hostToCheck);
while (rs.next()) {
System.out.println(rs.getString(1));
}
}
} catch (SQLException e) {
System.err.println("Database Error: " + e.getMessage());
}
}
}