5.7.2. 权限系统工作原理
MySQL权限系统保证所有的用户只执行允许做的事情。当你连接MySQL服务器时,你的身份由你从那儿连接的主机和你指定的用户名来决定。连接后发出请求后,系统根据你的身份和你想做什么来授予权限。
MySQL在认定身份中考虑你的主机名和用户名字,是因为几乎没有原因假定一个给定的用户在因特网上属于同一个人。例如,从office.com连接的用户joe不一定和从elsewhere.com连接的joe是同一个人。MySQL通过允许你区分在不同的主机上碰巧有同样名字的用户来处理它:你可以对joe从office.com进行的连接授与一个权限集,而为joe从elsewhere.com的连接授予一个不同的权限集。
MySQL存取控制包含2个阶段:
阶段1:服务器检查是否允许你连接。
阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够的权限实施它。例如,如果你从数据库表中选择(select)行或从数据库删除表,服务器确定你对表有SELECT权限或对数据库有DROP权限。
如果连接时你的权限被更改了(通过你和其它人),这些更改不一定立即对你发出的下一个语句生效。详情参见5.7.7节,“权限更改何时生效”。
服务器在mysql数据库的 授权表中保存权限信息(即在mysql数据库中)。当MySQL服务器启动时将这些表的内容读入内存,在5.7.7节,“权限更改何时生效”的环境下重新读取它们。访问控制决策取决于内存中的 授权表的份数。
一般情况,你通过GRANT和REVOKE语句间接来操作 授权表的内容,设置账户并控制个人的权限。参见13.5.1.3节,“GRANT和REVOKE语法”。下面讨论了 授权表的结构以及服务器与客户端交互操作时如何使用其内容。
服务器在存取控制的两个阶段使用mysql数据库中的user、db和host表,这些授权表中的列如下:
表名
user
db
host
列范围
Host
Host
Host
User
Db
Db
Password
User
权限列
Select_priv
Select_priv
Select_priv
Insert_priv
Insert_priv
Insert_priv
Update_priv
Update_priv
Update_priv
Delete_priv
Delete_priv
Delete_priv
Index_priv
Index_priv
Index_priv
Alter_priv
Alter_priv
Alter_priv
Create_priv
Create_priv
Create_priv
Drop_priv
Drop_priv
Drop_priv
Grant_priv
Grant_priv
Grant_priv
Create_view_priv
Create_view_priv
Create_view_priv
Show_view_priv
Show_view_priv
Show_view_priv
Create_routine_priv
Create_routine_priv
Alter_routine_priv
Alter_routine_priv
References_priv
References_priv
References_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv
Show_db_priv
Super_priv
Create_tmp_table_priv
Create_tmp_table_priv
Create_tmp_table_priv
Lock_tables_priv
Lock_tables_priv
Lock_tables_priv
Execute_priv
Repl_slave_priv
Repl_client_priv
安全列
ssl_type
ssl_cipher
x509_issuer
x509_subject
资源控制列
max_questions
max_updates
max_connections
max_user_connections
对存取控制的第二阶段(请求证实),服务器执行请求验证以确保每个客户端有充分的权限满足各需求。除了user、db和host授权表,如果请求涉及表,服务器可以另外参考tables_priv和columns_priv表。tables_priv和columns_priv表可以对表和列提供更精确的权限控制。这些表的列如下:
表名
tables_priv
columns_priv
范围列
Host
Host
Db
Db
User
User
Table_name
Table_name
Column_name
权限列
Table_priv
Column_priv
Column_priv
其它列
Timestamp
Timestamp
Grantor
Timestamp和Grantor列当前还未使用,这儿不再进一步讨论。
为了对涉及保存程序的请求进行验证,服务器将查阅procs_priv表。该表具有以下列:
表名
procs_priv
范围列
Host
Db
User
Routine_name
Routine_type
权限列
Proc_priv
其它列
Timestamp
Grantor
Routine_type列为ENUM列,值为'FUNCTION'或'PROCEDURE',表示行所指的程序类型。该列允许为同名函数和程序单独授权。
Timestamp和Grantor列当前还未使用,这儿不再进一步讨论。
每个授权表包含范围列和权限列:
l范围列决定表中每个条目(行)的范围,即,行适用的上下文。例如,一个user表行的Host和User值为'thomas.loc.gov'和'bob',将被用于证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表行的Host、User和Db列的值是'thomas.loc.gov'、'bob'和'reports'将用在bob从主机thomas.loc.gov联接访问reports数据库的时候。tables_priv和columns_priv表包含范围列,指出每个行适用的表或表/列的组合。procs_priv范围列指出每个行适用的保存程序。
对于检查存取的用途,比较Host值是忽略大小写的。User、Password、Db和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以后版本是忽略大小写的。
l 权限列指出由一个表行授予的权限,即,可实施什么操作。服务器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规则在5.7.6节,“访问控制, 阶段2:请求核实”描述。
范围列包含字符串,如下所述;每个列的默认值是空字符串:
列名
类型
Host
CHAR(60)
User
CHAR(16)
Password
CHAR(16)
Db
CHAR(64)
Table_name
CHAR(64)
Column_name
CHAR(64)
Routine_name
CHAR(64)
为了访问检查目的,Host值的比较对大小写不敏感。User、Password、Db和Table_name值对大小写敏感。Column_name值对大小写不敏感。
在user、db和host表中,所有权限列于单独的列内,被声明为ENUM('N','Y') DEFAULT 'N'。换句话说,每一个权限都可以被禁用和启用,并且 默认是禁用。
在tables_priv、columns_priv和procs_priv表中,权限列被声明为SET列。这些列的值可以包含该表控制的权限的组合:
表名
列名
可能的设置元素
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'
procs_priv
Proc_priv
'Execute', 'Alter Routine', 'Grant'
简单地说,服务器使用这样的授权表:
·user表范围列决定是否允许或拒绝到来的连接。对于允许的连接,user表授予的权限指出用户的全局(超级用户)权限。这些权限适用于服务器上的all数据库。
·db表范围列决定用户能从哪个主机存取哪个数据库。权限列决定允许哪个操作。授予的数据库级别的权限适用于数据库和它的表。
·当你想要一个给定的db表行应用于若干主机时,db和host表一起使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个数据库,在用户的db表行的Host值设为空值,然后将那些主机的每一个移入host表。这个机制详细描述在5.7.6节,“访问控制, 阶段2:请求核实”。
注释:host表不受GRANT和REVOKE语句的影响。大多数MySQL安装根本不需要使用该表。
·tables_priv和columns_priv表类似于db表,但是更精致:它们在表和列级应用而非在数据库级。授予表级别的权限适用于表和所有它的列。授予列级别的权限只适用于专用列。
· procs_priv表适用于保存的程序。授予程序级别的权限只适用于单个程序。
管理权限(例如RELOAD或SHUTDOWN等等)仅在user表中被指定。这是因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由在其他授权表中列出这样的权限。事实上,只需要查询user表来决定你是否执行一个管理操作。
FILE权限也仅在user表中指定。它不是管理性权限,但你在服务器主机上读或写文件的能力与你正在存取的数据库无关。
当mysqld服务器启动时,将授权表的内容读入到内存中。你可以通过FLUSH PRIVILEGES语句或执行mysqladmin flush-privileges或mysqladmin reload命令让它重新读取表。对授权表的更改生效在5.7.7节,“权限更改何时生效”描述。
当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一个好主意。要检查给定账户的权限,使用SHOW GRANTS语句。例如,要检查Host和User值分别为pc84.example.com和bob的账户所授予的权限,应通过语句:
mysql>SHOW GRANTS FOR 'bob'@'pc84.example.com';
一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves提供给MySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意:mysqlaccess仅用user、db和host表检查存取。它不检查tables_priv、columns_priv或procs_priv表中指定的表、列和程序级权限。
对于诊断权限相关的问题的其它帮助,参见5.7.8节,“拒绝访问错误的原因”。对于安全问题常规建议,参见5.6节,“一般安全问题”。