天天看点

MySQL权限系统分析讲解

MySQL 有一套先进的但非标准的安全 / 授权系统,掌握其授权机制是开始操作 MySQL 数据库必须要走的第一步,对于一个熟悉 SQL 基本操作的人来说,也是 MySQL 所有的知识中比较难以理解的一个部分。本节通过揭开其授权系统的运作机制,希望大家能够可以更好地操作和使用这个优秀的数据库系统。    MySQL 的安全系统是很灵活的,它允许你以多种不同方式设置用户权限。一般地,你可使用标准的 SQL 语句 GRANT 和 REVOKE 语句做,他们为你修改控制客户访问的授权表,然而,你可能由一个不支持这些语句的老版本的 MySQL (在 3 . 22 . 11 之前这些语句不起作用),或者你发觉用户权限看起来不是以你想要的方式工作。对于这种情况,了解 MySQL 授权表的结构和服务器如何利用它们决定访问权限是有帮助的,这样的了解允许你通过直接修改授权表增加、删除或修改用户权限,它也允许你在检查这些表时诊断权限问题。    MySQL授权表的结构   通过网络连接服务器的客户对 MySQL 数据库的访问由授权表内容来控制。这些表位于 mysql 数据库中,并在第一次安装 MySQL 的过程中初始化(运行 mysql_install_db 脚本)。授权表共有 5 个表: user 、 db 、 host 、 tables_priv 和 columns_priv 。    授权表user、db和host的结构和作用   表 1   授权表 user 、 db 和 host 的结构

MySQL权限系统分析讲解

    授权表的内容有如下用途:   · user 表    user 表列出可以连接服务器的用户及其口令,并且它指定他们有哪种全局(超级用户)权限。在 user 表启用的任何权限均是全局权限,并适用于所有数据库。例如,如果你启用了 DELETE 权限,在这里列出的用户可以从任何表中删除记录,所以在你这样做之前要认真考虑。   · db 表    db 表列出数据库,而用户有权限访问它们。在这里指定的权限适用于一个数据库中的所有表。   · host 表    host 表与 db 表结合使用在一个较好层次上控制特定主机对数据库的访问权限,这可能比单独使用 db 好些。这个表不受 GRANT 和 REVOKE 语句的影响,所以,你可能发觉你根本不是用它。    授权表tables_priv和columns_priv的结构和作用   表 2   授权表 tables_priv 和 columns_priv 的结构

授权表 tables_priv 授权表 columns_priv
作用域列
Host Host
Db Db
User User
Table_name Table_name
Column_name
权限列
Table_priv Column_priv
其他列
Timestamp Timestamp
Grantor

MySQL 没有 rows_priv 表,因为它不提供记录级权限,例如,你不能限制用户于表中包含特定列值的行。如果你确实需要这种能力,你必须用应用编程来提供。如果你想执行建议的记录级锁定,你可用 GET_LOCK ()函数做到。   授权表的内容有如下用途:   · tables_priv 表    tables_priv 表指定表级权限,在这里指定的一个权限适用于一个表的所有列。   · columns_priv 表    columns_priv 表指定列级权限。这里指定的权限适用于一个表的特定列。    tables_priv 和 columns_priv 表在 MySQL 3 . 22 . 11 版引进(与 GRANT 语句同时)。如果你有较早版本的 MySQL ,你的 mysql 数据库将只有 user 、 db 和 host 表。如果你从老版本升级到 3 . 22 . 11 或更新,而没有 tables_priv 和 columns_priv 表,运行 mysql_fix_privileges_tables 脚本创建它们。    用户的权限   权限信息用 user 、 db 、 host 、 tables_priv 和 columns_priv 表被存储在 mysql 数据库中(即在名为 mysql 的数据库中)。在 MySQL 启动时和在 7 . 5 权限修改何时生效所说的情况时,服务器读入这些数据库表内容。   数据库和表的权限   下列权限运用于数据库和表上的操作。   · SELECT   允许你使用 SELECT 语句从表中检索数据。 SELECT 语句只有在他们真正从一个表中检索行是才需要 select 权限,你可以执行某个 SELECT 语句,甚至没有任何到服务器上的数据库里的存取任何东西的许可。例如,你可使用 mysql 客户作为一个简单的计算器:    mysql> SELECT 1 + 1 ;    mysql> SELECT PI () *2 ;   · UPDATE   允许你修改表中的已有的记录。   · INSERT   允许在表中插入记录   · DELETE   允许你从表中删除现有记录。   · ALTER   允许你使用 ALTER TABLE 语句,这其实是一个简单的第一级权限,你必须由其他权限,这看你想对数据库实施什么操作。   · CREATE   允许你创建数据库和表,但不允许创建索引。   · DROP   允许你删除(抛弃)数据库和表,但不允许删除索引。   注意:如果你将 mysql 数据库的 drop 权限授予一个用户,该用户能抛弃存储了 MySQL 存取权限的数据库!   · INDEX   允许你创建并删除索引。   · REFERENCES   目前不用。    MySQL的管理权限   下列权限运用于控制服务器或用户授权能力的操作的管理性操作。   · FILE   允许你告诉服务器读或写服务器主机上的文件。该权限不应该随便授予,它很危险,见“回避授权表风险”。服务器确实较谨慎地保持在一定范围内使用该权限。你只能读任何人都能读的文件。你正在写的文件必须不是现存的文件,这防止你迫使服务器重写重要文件,如 /etc/passwd 或属于别人的数据库的数据目录。   如果你授权 FILE 权限,确保你不以 UNIX 的 root 用户运行服务器,因为 root 可在文件系统的任何地方创建新文件。如果你以一个非特权用户运行服务器,服务器只能在给用户能访问的目录中创建文件。   · GRANT   允许你将你自己的权限授予别人,包括 GRANT 。   · PROCESS   允许你通过使用 SHOW PROCESS 语句或 mysqladmin process 命令查看服务器内正在运行的线程(进程)的信息。这个权限也允许你用 KILL 语句或 mysqladmin kill 命令杀死线程。   你总是能看到或杀死你自己的线程。 PROCESS 权限赋予你对任何线程做这些事情的能力。   · RELOAD   允许你执行大量的服务器管理操作。你可以发出 FLUSH 语句,你也能指性 mysqladmin 的 reload 、 refresh 、 flush - hosts 、 flush - logs 、 flush - privileges 和 flush - tables 等命令。   · SHUTDOWN   允许你用 mysqladmin shutdown 关闭服务器。   在 user 、 db 和 host 表中,每一个权限以一个单独的列指定。这些列全部声明为一个 ENUM ( "N" , "Y" )类型,所以每个权的缺省值是“ N ”。在 tables_priv 和 columns_priv 中的权限以一个 SET 表示,它允许权限用一个单个列以任何组合指定。这两个表比其他三个表更新,这就是为什么它们使用更有效的表示方式的原因。(有可能在未来, user 、 db 和 host 表也用一个 SET 类型表示。)    授权表列的内容   作用域列内容   一些范围列要求文字值,但它们大多数允许通配符或其他特殊值。   表 3   作用域列的类型

字段名 类型
Host CHAR ( 60 )
User CHAR ( 16 )
Password CHAR ( 16 )
Db CHAR ( 64 ) ( tables_priv 和 columns_priv 表为 CHAR ( 60 ))

· Host   一个 Host 列值可以是一个主机名或一个 IP 地址。值 localhost 意味着本地主机,但它只在你用一个 localhost 主机名时才匹配,而不是你在使用主机名时。假如你的本地主机名是 pit . snake . net 并且在 user 表中有对你的两条记录,一个有一个 Host 值或 localhost ,而另一个有 pit . snake . net ,有 localhost 的记录将只当你连接 localhost 时匹配,其他在只在连接 pit . snake . net 时才匹配。如果你想让客户能以两种方式连接,你需要在 user 表中有两条记录。   你也可以用通配符指定 Host 值。可以使用 SQL 的模式字符“ % ”和“ _ ”并具有当你在一个查询中使用 LIKE 算符同样的含义(不允许 regex 算符)。  SQL 模式字符都能用于主机名和 IP 地址。如 %wisc . edu 匹配任何 wisc . edu 域内的主机,而 % . edu 匹配任何教育学院的主机。类似地, 192 . 168 . % 匹配任何在 192 . 168 B 类子网的主机,而 192 . 168 . 3 . % 匹配任何在 192 . 168 . 3 C 类子网的主机。    % 值匹配所有主机,并可用于允许一个用户从任何地方连接。一个空白的 Host 值等同于 % 。(例外:在 db 表中,一个空白 Host 值含义是“进一步检查 host 表”,该过程在“查询访问验证”中介绍。)   从 MySQL 3 . 23 起,你也可以指定带一个表明那些为用于网络地址的网络掩码的 IP 地址,如 192 . 168 . 128 . 0/17 指定一个 17 位网络地址并匹配其 IP 地址是 192 . 168 . 128 前 17 位的任何主机。   · User   用户名必须是文字的或空白。一个空白值匹配任何用户。 % 作为一个 User 值不意味着空白,相反它匹配一个字面上的 % 名字,这可能不是你想要的。   当一个到来的连接通过 user 表被验证而匹配的记录包含一个空白的 User 值,客户被认为是一个匿名用户。   · Password   口令值可以是空或非空,不允许用通配符。一个空口令不意味着匹配任何口令,它意味着用户必须不指定口令。   口令以一个加密过的值存储,不是一个字面上的文本。如果你在 Password 列中存储一个照字面上的口令,用户将不能连接! GRANT 语句和 mysqladmin password 命令为你自动加密口令,但是如果你用诸如 INSERT 、 REPLACE 、 UPDATE 或 SET PASSWORD 等命令,一定要用 PASSWORD ( "new_password" )而不是简单的 "new_password" 来指定口令。   · Db   在 columns_priv 和 tables_priv 表中, Db 值必须是真正的数据库名(照字面上),不允许模式和空白。在 db 和 host 中, Db 值可以以字面意义指定或使用 SQL 模式字符 '%' 或 '_' 指定一个通配符。一个 '%' 或空白匹配任何数据库。   · Table_name , Column_name   这些列中的值必须是照字面意思的表或列名,不允许模式和空白。   某些范围列被服务器视为大小写敏感的,其余不是。这些原则总结在下表中。特别注意 Table_name 值总是被看作大小写敏感的,即使在查询中的表名的大小写敏感性对待视服务器运行的主机的文件系统而定( UNIX 下是大小写敏感,而 Windows 不是)。   某些作用域列被服务器视为大小写敏感的,其余不是。这些原则总结在下表中。特别注意 Table_name 值总是被看作大小写敏感的,即使在查询中的表名的大小写敏感性对待视服务器运行的主机的文件系统而定( UNIX 下是大小写敏感,而 Windows 不是)。   表 4   作用域列的大小写敏感性

大小写敏感性
Host No
User Yes
Password Yes
Db Yes
Table_name Yes
Column_name No

授权表User、Db和Host的权限列的内容   在 user 、 db 和 host 表中,所有权限字段被声明为 ENUM ( 'N' , 'Y' )--每一个都可有值 'N' 或 'Y' ,并且缺省值是 'N' .   授权表 tables_priv 和 columns_priv 的权限列的内容   在 tables_priv 和 columns_priv 表中,权限字段被声明为 SET 字段:   表 5   授权表 tables_priv 和 columns_priv 的权限列的类型

表名 字段名 可能的集合成员
tables_priv Table_priv 'Select' ,  'Insert' ,  'Update' ,  'Delete' , 'Create' ,  'Drop' ,  'Grant' ,  'References' ,  'Index' ,  'Alter'
tables_priv Column_priv 'Select' ,  'Insert' ,  'Update' ,  'References'
columns_priv Column_priv 'Select' ,  'Insert' ,  'Update' ,  'References'

MySQL权限系统的工作原理   权限系统工作的一般过程    MySQL 权限系统保证所有的用户可以严格地做他们假定被允许做的事情。当你连接一个 MySQL 服务器时, 你的身份由你从那连接的主机和你指定的用户名来决定,系统根据你的身份和你想做什么来授予权限。    MySQL 在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假定一个给定的用户在因特网上属于同一个人。例如,用户从 whitehouse . gov 连接的 bill 不必和从 mosoft . com 连接 bill 是同一个人。  MySQL 通过允许你区分在不同的主机上碰巧有同样名字用户来处理它:你可以对从 whitehouse . gov 连接授与 bill 一个权限集,而为从 microsoft . com 的连接授予一个不同的权限集。    MySQL 存取控制包含 2 个阶段:   ·阶段 1 :服务器检查你是否允许连接。   ·阶段 2 :假定你能连接,服务器检查你发出的每个请求。看你是否有足够的权限实施它。例如,如果你从数据库中一个表精选( select )行或从数据库抛弃一个表,服务器确定你对表有 select 权限或对数据库有 drop 权限。   服务器在存取控制的两个阶段使用在 mysql 的数据库中的 user 、 db 和 host 表对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外参考 tables_priv 和 columns_priv 表。   简单地说,服务器使用这样的授权表:   · user 表范围字段决定是否允许或拒绝到来的连接。对于允许的连接,权限字段指出用户的全局(超级用户)权限。   · db 和 host 表一起使用:    db 表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定允许哪个操作。   当你想要一个给定的 db 条目应用于若干主机时, host 表作为 db 表的扩展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个数据库,在用户的 db 表的 Host 条目设为空值,然后将那些主机的每一个移入 host 表。    tables_priv 和 columns_priv 表类似于 db 表,但是更精致:他们在表和列级应用而非在数据库级。   注意管理权限( reload ,  shutdown , 等等)仅在 user 表中被指定。这是因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由在其他授权表中列出这样的权限。事实上,只需要请教 user 表来决定你是否执行一个管理操作。    file 权限也仅在 user 表中指定。它不是管理性权限,但你读或谢在服务器主机上的文件的的能力独立于你正在存取的数据库。   当 mysqld 服务器启动时,读取一次授权表内容。对授权表的更改生效在 7 . 5 权限修改何时生效。   一个有用的诊断工具是 mysqlaccess 脚本,由 Carlier Yves  提供给 MySQL 分发。使用-- help 选项调用 mysqlaccess 查明它怎样工作。注意: mysqlaccess 仅用 user 、 db 和 host 表仅检查存取。它不检查表或列级权限。    存取控制,阶段1:连接证实   当你试图联接一个 MySQL 服务器时,服务器基于你的身份和你是否能通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全具结你的存取,否则,服务器接受连接,然后进入阶段 2 并且等待请求。   你的身份基于 2 个信息:   ·你从那个主机连接   ·你的 MySQL 用户名   身份检查使用 3 个 user 表( Host ,  User 和 Password )范围字段执行。服务器只有在一个 user 表条目匹配你的主机名和用户名并且你提供了正确的口令时才接受连接。   在 user 表范围字段可以如下被指定:   一个 Host 值可以是主机名或一个 IP 数字,或 'localhost' 指出本地主机。   你可以在 Host 字段里使用通配符字符“ % ”和“ _ ”。   一个 Host 值 '%' 匹配任何主机名,一个空白 Host 值等价于 '%' 。注意这些值匹配能创建一个连接到你的服务器的任何主机!   通配符字符在 User 字段中不允许,但是你能指定空白的值,它匹配任何名字。如果 user 表匹配到来的连接的条目有一个空白的用户名,用户被认为是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空白的用户名被用于在连接期间的进一步的存取检查(即,在阶段 2 期间)。    Password 字段可以是空白的。这不意味着匹配任何口令,它意味着用户必须不指定一个口令进行连接。   非空白 Password 值代表加密的口令。  MySQL 不以任何人可以看的纯文本格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用 PASSWORD ()函数),并且与存储了 user 表中的已经加密的版本比较。如果他们匹配,口令是正确的。   下面的例子显示出各种 user 表中 Host 和 User 条目的值的组合如何应用于到来的连接:   表 6  Host 和 User 条目的值的组合

Host 值 User 值 被条目匹配的连接
'host . domain . cn' 'Gwen' Gwen , 从 host . domain . cn 连接
'host . domain . cn' '' 任何用户, 从 host . domain . cn 连接,
'%' 'Gwen' Gwen , 从任何主机连接
'%' '' 任何用户, 从任何主机连接
'% . loc . gov' 'Gwen' Gwen , 从在 loc . gov 域的任何主机连接
'x . y . %' 'Gwen' Gwen , 从 x . y . net 、 x . y . com , x . y . edu 等联接。(这或许无用)
'144 . 155 . 166 . 177' 'Gwen' Gwen , 从有 144 . 155 . 166 . 177 IP  地址的主机连接
'144 . 155 . 166 . %' 'Gwen' Gwen , 从 144 . 155 . 166 C 类子网的任何主机连接

既然你能在 Host 字段使用 IP 通配符值(例如, '144 . 155 . 166 . %' 匹配在一个子网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机为 144 . 155 . 166 . somewhere . com 。为了阻止这样的企图, MySQL 不允许匹配以数字和一个点起始的主机名,这样,如果你用一个命名为类似 1 . 2 . foo . com 的主机,它的名字决不会匹配授权表中 Host 列。只有一个 IP 数字能匹配 IP 通配符值。   一个到来的连接可以被在 user 表中的超过一个条目匹配。例如,一个由 Gwen 从 host . domain . cn 的连接匹配多个条目如上所述。如果超过一个匹配,服务器怎么选择使用哪个条目呢?服务器在启动时读入 user 表后通过排序来解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一个匹配的条目被使用。    MySQL 服务器按一种特定方式排序符授权表中的记录,然后通过按序浏览记录匹配到来的连接。找到的第一个匹配决定了被使用的记录。理解 MySQL 使用的排序顺序很重要,特别是对 user 表。   当服务器读取 user 表内容时,它根据在 Host 和 User 列中的值排序记录, Host 值起决定作用(相同的 Host 值排在一起,然后再根据 User 值排序)。然而,排序不是典序(按词排序),它只是部分是。要牢记的是字面上的词优先于模式。这意味着如果你正从 client . your . net 连接服务器而 Host 有 client . your . net 和 % . your . net 两个值,则第一个先选。类似地, % . your . net 优先于 % . net ,然后是 % 。 IP 地址的匹配也是这样的。总之一句话,越具体越优先。    user 表排序工作如下,假定 user 表看起来像这样:   +-----------+----------+-    | Host      | User     |  ...   +-----------+----------+-    | %         | root     |  ...    | %         | jerry    |  ...    | localhost | root     |  ...    | localhost |          |  ...   +-----------+----------+-   当服务器在表中读取时,它以最特定的 Host 值为先的次序排列( '%' 在 Host 列里意味着“任何主机”并且是最不特定的)。有相同 Host 值的条目以最特定的 User 值为先的次序排列(一个空白 User 值意味着“任何用户”并且是最不特定的)。最终排序的 user 表看起来像这样:   +-----------+----------+-    | Host      | User     |  ...   +-----------+----------+-    | localhost | root     |  ...    | localhost |          |  ...    | %         | jerry    |  ...    | %         | root     |  ...   +-----------+----------+-   当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹配。对于由 jeffrey 从 localhost 的一个连接,在 Host 列的 'localhost' 条目首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。( '%'/'jeffrey' 条目也将匹配,但是它不是在表中的第一匹配。)   这是另外一个例子。假定 user 表看起来像这样:   +----------------+----------+-    | Host           | User     |  ...   +----------------+----------+-    | %              | jerry    |  ...    | host . domain . cn |          |  ...   +----------------+----------+-   排序后的表看起来像这样:   +----------------+----------+-    | Host           | User     |  ...   +----------------+----------+-    | host . domain . cn |          |  ...    | %              | jerry    |  ...   +----------------+----------+-   一个由 jerry 从 host . domain . cn 的连接被第一个条目匹配,而一个由 jerry 从 whitehouse . gov 的连接被第二个匹配。   普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。先前的例子说明了这点,在那里一个由 jerry 从 host . domain . cn 的连接没被包含 'jerry' 作为 User 字段值的条目匹配,但是由没有用户名的题目匹配!   如果你有服务器连接的问题,打印出 user 表并且手工排序它看看第一个匹配在哪儿进行。    存取控制,阶段2:请求证实   一旦你建立了一个连接,服务器进入阶段 2 。对在此连接上进来的每个请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子 user 、 db 、 host 、 tables_priv 或 columns_priv 表的任何一个。授权表用 GRANT 和 REVOKE 命令操作。(你可以发觉参考第七章 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。)    user 表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库是什么均适用。例如,如果 user 表授予你 delete 权限, 你可以删除在服务器主机上从任何数据库删除行!换句话说, user 表权限是超级用户权限。只把 user 表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户,你应该把在 user 表中的权限设成 'N' 并且仅在一个特定数据库的基础上授权, 使用 db 和 host 表。    db 和 host 表授予数据库特定的权限。在范围字段的值可以如下被指定:   通配符字符“ % ”和“ _ ”可被用于两个表的 Host 和 Db 字段。   在 db 表的 '%'Host 值意味着“任何主机”,在 db 表中一个空白 Host 值意味着“对进一步的信息咨询 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 字段不能包含通配符或空白。    tables_priv 和 columns_priv 表在 Host 、 Db 和 User 字段上被排序。这类似于 db 表的排序,尽管因为只有 Host 字段可以包含通配符,但排序更简单。   请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是不同于使解释更简单。)   对管理请求( shutdown 、 reload 等等),服务器仅检查 user 表条目,因为那是唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。例如,如果你想要执行 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 )让你确保你的存取权限实际上以你认为的方式被设置。    来源:网络   作者:不详