服务器接受连接后,进入访问控制的第 2 阶段。对于您通过连接发出的每个请求,服务器都会确定您要执行的操作,然后检查您的权限是否足够。这就是授权表中的特权列发挥作用的地方。这些权限可以来自user、
db、tables_priv、
columns_priv或procs_priv
表中的任何一个。(您可能会发现参考
第 6.2.3 节“授权表”很有帮助,其中列出了每个授权表中的列。)
该user表授予全局权限。帐户的
user表行指示在全局基础上应用的帐户权限,无论默认数据库是什么。例如,如果user
表授予您DELETE
权限,您可以从服务器主机上任何数据库中的任何表中删除行。明智的做法是只将表中的权限授予
user需要它们的人,例如数据库管理员。对于其他用户,将user表中的所有权限保留为'N'
并仅授予更特定级别的权限(对于特定数据库、表、列或例程)。
该db表授予特定于数据库的权限。此表的范围列中的值可以采用以下形式:
服务器将db表读入内存,并在读取表的同时进行排序
user。db服务器根据Host、
Db和Userscope 列对表进行排序
。与user表格一样,排序将最具体的值放在最前面,最不具体的值放在最后,当服务器查找匹配行时,它会使用它找到的第一个匹配项。
、和表授予特定于表tables_priv、
特定于列和特定于例程的权限。这些表的范围列中的值可以采用以下形式:
columns_privprocs_priv
通配符
%和_可以在Host列中使用。这些与使用运算符执行的模式匹配操作具有相同的含义LIKE。一个
'%'或空白Host值表示“任何主机。”、
Db、Table_name和Column_name列Routine_name不能包含通配符或为空。
服务器根据、
和列对tables_priv、
columns_priv和表进行
排序。这类似于表排序,但更简单,因为只有列可以包含通配符。
procs_privHostDbUserdbHost
服务器使用排序后的表来验证它收到的每个请求。对于需要管理权限(例如SHUTDOWN或
RELOAD)的请求,服务器仅检查
user表行,因为这是唯一指定管理权限的表。如果该行允许请求的操作,则服务器授予访问权限,否则拒绝访问。例如,如果你想执行mysqladmin shutdown但你的user表行没有授予SHUTDOWN你权限,服务器甚至不检查
db表就拒绝访问。(后一个表没有
Shutdown_priv列,所以不需要检查。)
对于与数据库相关的请求(INSERT、
UPDATE等),服务器首先检查
user表行中用户的全局权限。如果该行允许请求的操作,则授予访问权限。如果表中的全局权限user不足,则服务器从表中确定用户的数据库特定权限
db:
服务器在表中查找、和列
db的匹配项。HostDbUserHost和 列User与连接用户的主机名和 MySQL 用户名相匹配。该
Db列与用户要访问的数据库相匹配。如果没有行
Host和User,则访问被拒绝。
在确定
db表行授予的特定于数据库的权限后,服务器将它们添加到表授予的全局权限user中。如果结果允许请求的操作,则访问被授予。否则,服务器依次检查用户在tables_priv和
columns_priv表中的表和列权限,将这些权限添加到用户权限中,并根据结果允许或拒绝访问。对于存储例程操作,服务器使用
procs_priv表而不是
tables_privand
columns_priv。
用布尔术语表示,前面关于如何计算用户权限的描述可以总结如下:
global privileges
OR database privileges
OR table privileges
OR column privileges
OR routine privileges
可能不清楚为什么,如果最初发现全局权限不足以执行请求的操作,服务器会在稍后将这些权限添加到数据库、表和列权限中。原因是一个请求可能需要不止一种类型的特权。例如,如果您执行一条
INSERT INTO ...
SELECT语句,您需要
INSERT和
SELECT权限。您的权限可能是user表行授予一个全局权限,而db表行授予其他专门针对相关数据库。在这种情况下,您拥有执行请求所需的权限,但服务器无法单独从您的全局权限或数据库权限中分辨出来。它必须根据组合的权限做出访问控制决策。