服务器接受连接后,进入权限控制的第二阶段。对于您通过连接发出的每个请求,服务器确定您要执行的操作,然后检查您的权限是否足够。这是授权表中的权限列发挥作用的地方。这些权限来自系统表user
、global_grants
、db
、tables_priv
、columns_priv
或procs_priv
。
user表和global_grants表授予全局特权。这些表中给定帐户的行记录表示在全局基础上适用的帐户权限,而无论默认数据库是什么。例如,如果user表授予您DELETE权限,您可以从服务器主机上任何数据库的任何表中删除行。明智的做法是将user表中的特权只授予需要它们的人,例如数据库管理员。对于其他用户,将user表中的所有权限设置为'N'
db表授予特定于数据库的权限。此表的范围列中的值可以采用以下形式:
- 空白用户值与匿名用户匹配。非空白值从字面上匹配;用户名中没有通配符。
- 通配符%和_可以在Host和Db列中使用。它们与使用LIKE运算符执行的模式匹配操作具有相同的含义。如果您想在授予权限时按字面意思使用任一字符,则必须使用反斜杠来转义。例如,要将下划线字符(_)作为库名的一部分,请在GRANT语句中将其指定为\_。
- 一个
'%'
或空白Host
值表示任何主机。 - 一个
'%'
或空白Db
值表示任何数据库。
服务器将db
表读入内存,并在读取user
表的同时对其进行排序。服务器根据Host
、Db
和User
范围列对db
表进行排序。与user
表一样,排序将最具体的值放在首位,最不具体的值放在最后,当服务器查找匹配的行时,它使用找到的第一个匹配行。
tables_priv
、columns_priv
和procs_priv
表授予特定于表、特定于列和特定于例程的权限。这些表的范围列中的值可以采用以下形式:
-
通配符
%
和_
可以在Host
列中使用。它们与使用like运算符执行的模式匹配操作具有相同的含义。 - 一个
'%'
或空白Host
值表示任何主机。 在Db
、Table_name
、Column_name
和Routine_name
列中不能包含通配符或为空。
服务器根据columns_priv
列对Host
、Db
、User
和tables_priv
表进行排序。这类似于procs_priv
和db
表排序,但更简单,因为只有Host
列可以包含通配符。
服务器使用排序后的表来验证它收到的每个请求。对于需要shutdown或reload等管理权限的请求,服务器只检查user和global_privilege表,因为它们是唯一指定管理权限的表。如果这些表中的帐户行权限允许请求的操作,则服务器会授予访问权限,否则拒绝访问。例如,如果您想执行mysqladmin shutdown,但您的user表行没有授予您shutdown权限,服务器甚至不检查db表就拒绝访问(后一个表不包含Shutdown_priv列,因此无需检查。)
对于与数据库相关的请求(INSERT、UPDATE等),服务器首先检查用户在user表行中的全局权限(减去部分撤销施加的任何权限限制)。如果该行允许请求的操作,则授予访问权限。如果user表中的全局权限不足,则服务器从db表中确定用户的数据库特定权限:
-
服务器在
db
表中查找Host
、Db
和User
列的匹配。 -
将
Host
和User
列与连接用户的主机名和MySQL用户名匹配。 -
将
Db
列与用户想要访问的数据库相匹配。 -
如果
Host
和User
没有对应的权限记录,则拒绝访问。
确定db
表行授予的数据库特定权限后,服务器将它们添加到user
表授予的全局权限中。如果结果允许所请求的操作,则授予访问权限。否则,服务器依次检查用户表和tables_priv
和columns_priv
表中的列权限,将这些权限添加到用户权限中,并根据结果允许或拒绝访问。对于存储过程操作权限,服务器使用procs_priv
表而不是tables_priv
和columns_priv
。
用布尔术语表示,前面关于如何计算用户权限的描述可以总结如下:
global privileges
OR database privileges
OR table privileges
OR column privileges
OR routine privileges
如果最初发现全局权限不足以执行请求的操作,则服务器稍后将这些权限添加到数据库、表和列权限,这些行为看起来可能不太直观,我们来解释一下,如果执行INSERT INTO… SELECT语句,则需要INSERT和SELECT两种权限。您的权限可能是这样的:用户表行授予一种全局权限,而数据库表行授予另一种专门针对相关数据库的权限。在这种情况下,您拥有执行请求所需的权限,但服务器无法仅从您的全局权限或数据库权限判断出这一点。它必须基于组合权限做出访问控制决策。