### 6.2.23 基于 SQL 的帐户活动审计

应用程序可以使用以下准则来执行基于 SQL 的审计，将数据库活动与 MySQL 帐户联系起来。

MySQL 帐户对应于`mysql.user`系统表。当客户端成功连接时，服务器将客户端验证到此表中的特定行。这`用户`和`主持人`此行中的列值唯一标识帐户并对应于`'*`用户名`*'@'*`主机名`*'`SQL 语句中账户名的书写格式。

用于对客户端进行身份验证的帐户决定了客户端具有哪些权限。通常情况下，[`当前用户（）`](information-functions.html#function_current-user)可以调用函数来确定客户端用户的帐户。它的价值是由`用户`和`主持人`的列`用户`帐户的表行。

但是，在某些情况下，[`当前用户（）`](information-functions.html#function_current-user)value 不对应于客户端用户，而是对应于不同的帐户。这发生在权限检查不是基于客户帐户的上下文中：

-   使用定义的存储例程（过程和函数）`SQL 安全定义器`特征

-   定义的视图`SQL 安全定义器`特征

-   触发器和事件

    在这些情况下，权限检查是针对`定义者`帐户和[`当前用户（）`](information-functions.html#function_current-user)指该帐户，而不是调用存储的例程或视图或导致触发器激活的客户的帐户。要确定调用用户，您可以调用[`用户（）`](information-functions.html#function_user)函数，它返回一个值，该值指示客户端提供的实际用户名和客户端连接的主机。但是，该值不一定直接对应于`用户`表，因为[`用户（）`](information-functions.html#function_user)value 从不包含通配符，而 account 值（由[`当前用户（）`](information-functions.html#function_current-user)) 可能包含用户名和主机名通配符。

    例如，空白用户名匹配任何用户，因此`''@'本地主机'`使客户端能够以匿名用户身份从本地主机以任何用户名进行连接。在这种情况下，如果客户端连接为`用户1`从本地主机，[`用户（）`](information-functions.html#function_user)和[`当前用户（）`](information-functions.html#function_current-user)返回不同的值：


```
mysql> SELECT USER(), CURRENT_USER();
+-----------------+----------------+
| USER()          | CURRENT_USER() |
+-----------------+----------------+
| user1@localhost | @localhost     |
+-----------------+----------------+
```

帐户的主机名部分也可以包含通配符。如果主机名包含`'%'`要么`'_'`模式字符或使用网络掩码表示法，该帐户可用于从多个主机连接的客户端和[`当前用户（）`](information-functions.html#function_current-user)值不表示是哪一个。例如，帐户`'user2'@'%.example.com'`可以使用`用户2`从任何主机连接`例子.com`领域。如果`用户2`从连接`remote.example.com`,[`用户（）`](information-functions.html#function_user)和[`当前用户（）`](information-functions.html#function_current-user)返回不同的值：

```
mysql> SELECT USER(), CURRENT_USER();
+--------------------------+---------------------+
| USER()                   | CURRENT_USER()      |
+--------------------------+---------------------+
| user2@remote.example.com | user2@%.example.com |
+--------------------------+---------------------+
```

如果应用程序必须调用[`用户（）`](information-functions.html#function_user)用于用户审计（例如，如果它从触发器内部进行审计），但还必须能够关联[`用户（）`](information-functions.html#function_user)账户中的价值`用户`表中，有必要避免帐户中包含通配符`用户`要么`主持人`柱子。具体来说，不允许`用户`为空（创建匿名用户帐户），并且不允许使用模式字符或网络掩码表示法`主持人`价值观。所有帐户必须有一个非空`用户`值和字面量`主持人`价值。

对于前面的例子，`''@'本地主机'`和`'user2'@'%.example.com'`帐户应更改为不使用通配符：

```
RENAME USER ''@'localhost' TO 'user1'@'localhost';
RENAME USER 'user2'@'%.example.com' TO 'user2'@'remote.example.com';
```

如果`用户2`必须能够从多个主机连接`例子.com`域，每个主机都应该有一个单独的帐户。

提取用户名或主机名部分[`当前用户（）`](information-functions.html#function_current-user)要么[`用户（）`](information-functions.html#function_user)值，使用[`SUBSTRING_INDEX()`](string-functions.html#function_substring-index)功能：

```
mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',1);
+---------------------------------------+
| SUBSTRING_INDEX(CURRENT_USER(),'@',1) |
+---------------------------------------+
| user1                                 |
+---------------------------------------+

mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',-1);
+----------------------------------------+
| SUBSTRING_INDEX(CURRENT_USER(),'@',-1) |
+----------------------------------------+
| localhost                              |
+----------------------------------------+
```
