После установления соединения сервер приступает к выполнению второго
этапа. Для каждого поступающего запроса сервер проверяет, имеется ли у вас
достаточно привилегий для его выполнения, основываясь при этом на типе
операции, которую вы хотите выполнить. Теперь в действие вступают поля
привилегий в таблицах привилегий. Информация о привилегиях может
находиться в любой из таблиц привилегий - user
, db
, host
, tables_priv
или
columns_priv
. Обработка таблиц привилегий осуществляется с помощью команд
GRANT
и REVOKE
. Обратитесь к разделу See Раздел 4.3.1, «Синтаксис команд GRANT
и REVOKE
». Интерес
может представлять раздел See Раздел 4.2.6, «Как работает система привилегий», в котором перечислены поля, имеющиеся в каждой из
таблиц привилегий.
Таблица user
предоставляет привилегии глобального характера, и их
применение не зависит от того, в какой базе вы работаете в данный момент.
Например, если таблица user
предоставляет пользователю привилегию DELETE
,
он может удалять строки из любой базы данных на серверном хосте! Иными
словами, привилегии в таблице user
- это привилегии суперпользователя.
Поэтому целесообразно предоставлять привилегии в таблице user
только
суперпользователям, таким как администраторы сервера или администраторы
баз данных. Что касается других пользователей, для их привилегий в таблице
user следует установить значение 'N'
и предоставлять им привилегии только
на уровне баз данных, используя для этого таблицы db
и host
.
Таблицы db
и host
предоставляют привилегии на уровне базы данных. Значения
в полях контекста могут задаваться следующим образом:
Шаблонные символы '
%
' и '_
' могут использоваться в поляхHost
иDb
любой таблицы. Если вы хотите использовать символ '_
' как часть имени базы данных, укажите его как '\_
' в оператореGRANT
.Значение
'%'
в колонкеHost
таблицыdb
означает ``любой хост''. Пустое значение в полеHost
таблицыdb
означает ``за дополнительной информацией следует обратиться к таблицеhost
''.Значение
'%'
или пустое значение в полеHost
таблицыhost
означает ``любой хост''.Значение
'%'
или пустое значение в полеDb
любой из таблиц означает ``любая база данных''.Пустое значение в поле
User
любой из таблиц соответствует анонимному пользователю.
Таблицы db
и host
считываются и сортируются при запуске сервера (тогда же,
когда он считывает таблицу user
). Таблица db
сортируется по полям
контекста Host
, Db
и User
, а таблица host
- по полям контекста Host
и Db
.
Как и в случае таблицы user
, при сортировке первыми отбираются наиболее
конкретные значения, а последними - наименее конкретные, а когда сервер
производит поиск совпадающих записей, используется первая совпадающая
запись, которую он находит.
Таблицы tables_priv
и columns_priv
предоставляют привилегии соответственно
на уровне таблиц и столбцов. Значения в полях контекста задаются следующим
образом:
В обеих таблицах в поле
Host
можно использовать шаблонные символы '%
' и '_
'.-
В обеих таблицах
'%'
или пустое значение в полеHost
означает ``любой хост''.В обеих таблицах в полях
Db
,Table_name
иColumn_name
запрещено использовать шаблонные символы или пустое значение.
Таблицы_priv
и columns_priv
сортируются по полям Host
, Db
и User
. Эта
сортировка проводится так же, как и в таблице db
, хотя в данном случае
задача несколько упрощается, т.к. шаблонные символы могут встретиться
только в поле Host
.
Ниже описывается процесс верификации запроса. (Если вы хорошо знакомы с исходным кодом проверки доступа, то заметите некоторые отличия: приведенное здесь описание несколько упрощено, чтобы сделать его более понятным, однако оно соответствует тому, что в действительности делает код).
Для запросов на администрирование (SHUTDOWN
, RELOAD
, etc.) сервер
проверяет запись только в таблице user
, т.к. это единственная таблица,
которая определяет привилегии администрирования. Доступ предоставляется
при условии, что выбранная запись разрешает затребованные операции, и
запрещается в противном случае. Например, вы хотите завершить работу mysql
с помощью mysqladmin shutdown
, но ваша запись в таблице user
не
предоставляет вам привилегию SHUTDOWN
. В этом случае в доступе будет
отказано без дальнейшей проверки таблицы db
и host
(поскольку в них
отсутствует столбец Shutdown_priv
, в такой проверке нет необходимости).
В случае запросов, относящихся к базам данных (INSERT
, UPDATE
и т.д.),
сервер сначала проверяет глобальные привилегии пользователя (привилегии
суперпользователя), просматривая запись в таблице user
. Если эта запись
разрешает затребованную операцию, доступ предоставляется. Если глобальные
привилегии, указанные в таблице user
, недостаточны, сервер проверяет
таблицы db
и host
и определяет привилегии пользователя на уровне баз
данных:
Сервер просматривает таблицу
db
в поисках записи с подходящими значениями в поляхHost
,Db
иUser
. ПоляHost
иUser
сравниваются с именем подключающегося хоста и именем пользователя MySQL. ПолеDb
сравнивается с именем базы данных, к которой пользователь хочет получить доступ. Если запись с подходящими значениями в поляхHost
иUser
отсутствует, в доступе будет отказано.Если же в таблице
db
имеется подходящая запись и значение в полеHost
- не пустое, эта запись определяет привилегии пользователя, касающиеся базы данных.Если же в подходящей записи, выбранной в таблице
db
, значение в поле Host пустое, это означает, что перечень хостов, которым разрешен доступ к требуемой базе данных, приведен в таблицеhost
. В этом случае дальнейший поиск производится в таблицеhost
, где ищется запись с подходящими значениями в поляхHost
иDb
. Если ни одной подходящей записи в таблицеhost
нет, в доступе будет отказано. Если такая запись имеется, привилегии пользователя на уровне базы данных вычисляются путем логического умножения (не логического сложения!) привилегий, найденных в записях, которые выбраны в таблицахdb
иhost
. Другими словами, пользователю назначаются те привилегии, для которых в обеих записях установлено значение'Y'
. (Этот способ можно использовать следующим образом: предоставить всеобщие привилегии в записи, хранящейся в таблицеdb
, а затем выборочно ограничить их отдельно по каждому хосту, используя для этого записи в таблицеhost
.)
Определив привилегии на уровне базы данных, предоставляемые записями в
таблицах db
и host
, сервер добавляет их к глобальным привилегиям, заданным
в таблице user
. Если в результате привилегий оказывается достаточно для
выполнения затребованной операции, доступ предоставляется. В противном
случае сервер проверяет по таблицам tables_priv
и columns_priv
привилегии
пользователя на уровне таблиц и столбцов и добавляет их к уже имеющимся
привилегиям. В зависимости от полученного результата доступ либо
предоставляется, либо нет.
Если приведенное выше описание вычислений привилегий пользователя перевести на язык алгебры логики, используя логические операторы, то в результате получится примерно следующее:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges
Сам по себе алгоритм определения привилегий на первый взгляд может
показаться неочевидным. И в самом деле, если первоначально глобальных
привилегий, определяемых таблицей user
, оказывается недостаточно для
выполнения затребованной операции, то зачем впоследствии эти вроде бы
бесполезные привилегии добавляются к привилегиям на уровне баз данных,
таблиц и столбцов? Смысл такого добавления заключается в том, что для
выполнения запроса может потребоваться не один, а несколько типов
привилегий. Например, для выполнения оператора INSERT ... SELECT
вам
потребуется как привилегия INSERT
, так и привилегия SELECT
. Ваши
привилегии могут быть таковы, что запись в таблице user предоставляет вам
одну привилегию, а запись в таблице db
- другую. Другими словами,
привилегии, необходимые для выполнения запроса, у вас есть, но сервер не
может выяснить при просмотре каждой таблицы в отдельности, и поэтому
привилегии, предоставляемые записями из обеих таблиц, должны быть
объединены.
Таблицу host
можно использовать еще для одной цели - для поддержки списка
надежных серверов.
В таблицах на TcX host
содержит список всех машин локальной сети. Им
предоставляются все привилегии.
Таблицу host
можно также использовать для регистрации хостов, которые
являются ненадежными. Предположим, одна из ваших машин -
public.your.domain
находится в общедоступной области, которую вы считаете
незащищенной. В таком случае можно разрешить доступ всем хостам вашей
сети, за исключением одной ``неблагонадежной'' машины, используя записи в
таблице host
, подобные приведенным ниже:
+--------------------+----+- | Host | Db | ... +--------------------+----+- | public.your.domain | % | ... (для всех привилегий установлено значение 'N') | %.your.domain | % | ... (для всех привилегий установлено значение 'Y') +--------------------+----+-
Естественно, всегда нужно протестировать записи в таблицах привилегий
(например, с помощью mysqlaccess
), чтобы убедиться в том, что привилегии
доступа установлены вами действительно так, как задумано.