Управление доступом, этап 2: верификация запросов
После установления соединения сервер приступает к выполнению второго этапа. Для каждого поступающего запроса сервер проверяет, имеется ли у вас достаточно привилегий для его выполнения, основываясь при этом на типе операции, которую вы хотите выполнить. Теперь в действие вступают поля привилегий в таблицах привилегий. Информация о привилегиях может находиться в любой из таблиц привилегий - user , db , host , tables_priv или columns_priv . Обработка таблиц привилегий осуществляется с помощью команд GRANT и REVOKE . Обратитесь к разделу интаксис команд GRANT и REVOKE " class=intext>Синтаксис команд GRANT и REVOKE . Интерес может представлять раздел Как работает система привилегий, в котором перечислены поля, имеющиеся в каждой из таблиц привилегий.
Таблица user предоставляет привилегии глобального характера, и их применение не зависит от того, в какой базе вы работаете в данный момент. Например, если таблица user предоставляет пользователю привилегию DELETE , он может удалять строки из любой базы данных на серверном хосте! Иными словами, привилегии в таблице user - это привилегии суперпользователя. Поэтому целесообразно предоставлять привилегии в таблице user только суперпользователям, таким как администраторы сервера или администраторы баз данных. Что касается других пользователей, для их привилегий в таблице user следует установить значение "N" и предоставлять им привилегии только на уровне баз данных, используя для этого таблицы db и host .
Таблицы db и host предоставляют привилегии на уровне базы данных. Значения в полях контекста могут задаваться следующим образом:
Шаблонные символы "%" и "_" могут использоваться в полях Host и Db любой таблицы.
Значение "%" в колонке 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 ), чтобы убедиться в том, что привилегии доступа установлены вами действительно так, как задумано.
1 2 3 4 5 6 7 8
8 8 8
| |