8.2.23 Аудит активности учетных записей на основе SQL
Приложения могут использовать следующие рекомендации для выполнения аудита на основе SQL, который связывает активность базы данных с учетными записями MySQL.
Учетные записи MySQL соответствуют строкам в таблице системы mysql.user. При успешном подключении клиента сервер аутентифицирует клиента по определенной строке в этой таблице. Значения столбцов User и Host в этой строке однозначно идентифицируют учетную запись и соответствуют формату ', в котором имена учетных записей записываются в операторах SQL.user_name'@'host_name'
Используемая для аутентификации клиента учетная запись определяет, какими привилегиями обладает клиент. Обычно, для определения учетной записи клиента можно вызвать функцию CURRENT_USER(). Ее значение формируется из столбцов User и Host строки таблицы user для соответствующей учетной записи.
Однако, существуют ситуации, в которых значение CURRENT_USER() соответствует не пользователю-клиенту, а другой учетной записи. Это происходит в контекстах, когда проверка привилегий не основана на учетной записи клиента:
Хранящиеся процедуры (процедуры и функции), определенные с характеристикой
SQL SECURITY DEFINERПредставления, определенные с характеристикой
SQL SECURITY DEFINERТриггеры и события
В этих контекстах проверка привилегий выполняется относительно учетной записи DEFINER, и CURRENT_USER() ссылается на эту учетную запись, а не на учетную запись клиента, вызвавшего хранимую процедуру или представление, или вызвавшего активацию триггера. Для определения вызывающего пользователя можно вызвать функцию USER(), которая возвращает значение, указывающее фактическое имя пользователя, предоставленное клиентом, и хост, с которого подключился клиент. Однако это значение не обязательно напрямую соответствует учетной записи в таблице user, поскольку значение USER() никогда не содержит подстановочных символов, тогда как значения учетных записей (возвращаемые функцией CURRENT_USER()) могут содержать подстановочные символы имени пользователя и имени хоста.
Например, пустое имя пользователя соответствует любому пользователю, поэтому учетная запись ''@'localhost' позволяет клиентам подключаться как анонимному пользователю с локального хоста с любым именем пользователя. В этом случае, если клиент подключается как user1 с локального хоста, USER() и CURRENT_USER() возвращают разные значения:
mysql> SELECT USER(), CURRENT_USER();
+-----------------+----------------+
| USER() | CURRENT_USER() |
+-----------------+----------------+
| user1@localhost | @localhost |
+-----------------+----------------+
Часть имени хоста учетной записи также может содержать подстановочные символы. Если имя хоста содержит символ шаблона '%' или '_' или использует нотацию подсети, учетная запись может использоваться для клиентов, подключающихся с нескольких хостов, и значение CURRENT_USER() не указывает, с какого именно. Например, учетная запись 'user2'@'%.example.com' может использоваться клиентом user2 для подключения с любого хоста в домене example.com. Если user2 подключается с remote.example.com, USER() и CURRENT_USER() возвращают разные значения:
mysql> SELECT USER(), CURRENT_USER();
+--------------------------+---------------------+
| USER() | CURRENT_USER() |
+--------------------------+---------------------+
| user2@remote.example.com | user2@%.example.com |
+--------------------------+---------------------+
Если приложению необходимо вызвать USER() для аудита пользователя (например, если оно выполняет аудит внутри триггеров), но также необходимо связать значение USER() с учетной записью в таблице user, необходимо избежать учетных записей, содержащих подстановочные символы в столбце User или Host. В частности, не допускайте, чтобы User было пустым (что создает анонимную учетную запись), и не допускайте символы шаблонов или нотации подсети в значениях Host. Все учетные записи должны иметь непустое значение User и буквальное значение Host.
В отношении предыдущих примеров учетные записи ''@'localhost' и 'user2'@'%.example.com' следует изменить, чтобы не использовать подстановочные символы:
RENAME USER ''@'localhost' TO 'user1'@'localhost';
RENAME USER 'user2'@'%.example.com' TO 'user2'@'remote.example.com';
Если user2 необходимо подключаться с нескольких хостов в домене example.com, для каждого хоста должна быть отдельная учетная запись.
Для извлечения части имени пользователя или имени хоста из значения CURRENT_USER() или USER() используйте функцию 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 |
+----------------------------------------+
© 2025 Oracle
Licensed under the GPLv2 License.