6.2.18 Аудит активности учётных записей на основе 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.