5.7.2. 权限系统工作原理

MySQL权限系统保证所有的用户只执行允许做的事情。当你连接MySQL服务器时,你的身份由你从那儿连接的主机你指定的用户名来决定。连接后发出请求后,系统根据你的身份和你想做什么来授予权限。

MySQL在认定身份中考虑你的主机名和用户名字,是因为几乎没有原因假定一个给定的用户在因特网上属于同一个人。例如,从office.com连接的用户joe不一定和从elsewhere.com连接的joe是同一个人。MySQL通过允许你区分在不同的主机上碰巧有同样名字的用户来处理它:你可以对joeoffice.com进行的连接授与一个权限集,而为joeelsewhere.com的连接授予一个不同的权限集。

MySQL存取控制包含2个阶段:

  • 阶段1:服务器检查是否允许你连接。
  • 阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够的权限实施它。例如,如果你从数据库表中选择(select)行或从数据库删除表,服务器确定你对表有SELECT权限或对数据库有DROP权限。

如果连接时你的权限被更改了(通过你和其它人),这些更改不一定立即对你发出的下一个语句生效。详情参见5.7.7节,“权限更改何时生效”

服务器在mysql数据库的 授权表中保存权限信息(即在mysql数据库中)。当MySQL服务器启动时将这些表的内容读入内存,在5.7.7节,“权限更改何时生效”的环境下重新读取它们。访问控制决策取决于内存中的 授权表的份数。

一般情况,你通过GRANTREVOKE语句间接来操作 授权表的内容,设置账户并控制个人的权限。参见13.5.1.3节,“GRANT和REVOKE语法”。下面讨论了 授权表的结构以及服务器与客户端交互操作时如何使用其内容。

服务器在存取控制的两个阶段使用mysql数据库中的userdbhost表,这些授权表中的列如下:

表名

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

 

 

对存取控制的第二阶段(请求证实),服务器执行请求验证以确保每个客户端有充分的权限满足各需求。除了userdbhost授权表,如果请求涉及表,服务器可以另外参考tables_privcolumns_priv表。tables_privcolumns_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

 

TimestampGrantor列当前还未使用,这儿不再进一步讨论。

为了对涉及保存程序的请求进行验证,服务器将查阅procs_priv表。该表具有以下列:

表名

procs_priv

范围列

Host

 

Db

 

User

 

Routine_name

 

Routine_type

权限列

Proc_priv

其它列

Timestamp

 

Grantor

Routine_type列为ENUM列,值为'FUNCTION''PROCEDURE',表示行所指的程序类型。该列允许为同名函数和程序单独授权。

TimestampGrantor列当前还未使用,这儿不再进一步讨论。

每个授权表包含范围列和权限列:

l        范围列决定表中每个条目(行)的范围,即,行适用的上下文。例如, 一个user表行的HostUser值为'thomas.loc.gov''bob'将被用于证实来自主机thomas.loc.govbob对服务器的连接。同样,一个db表行的HostUserDb列的值是'thomas.loc.gov''bob''reports'将用在bob从主机thomas.loc.gov联接访问reports数据库的时候。tables_privcolumns_priv表包含范围列,指出每个行适用的表或表/列的组合。procs_priv范围列指出每个行适用的保存程序。

对于检查存取的用途,比较Host值是忽略大小写的。UserPasswordDbTable_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值的比较对大小写不敏感。UserPasswordDbTable_name值对大小写敏感。Column_name值对大小写不敏感。

userdbhost表中,所有权限列于单独的列内,被声明为ENUM('N','Y') DEFAULT 'N'换句话说每一个权限都可以被禁用和启用,并且 默认是禁用

tables_privcolumns_privprocs_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表行应用于若干主机时,dbhost表一起使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个数据库,在用户的db表行的Host值设为空值,然后将那些主机的每一个移入host表。这个机制详细描述在5.7.6节,“访问控制, 阶段2:请求核实”

释:host表不受GRANTREVOKE语句的影响。大多数MySQL安装根本不需要使用该表。

·         tables_privcolumns_priv表类似于db表,但是更精致:它们在表和列级应用而非在数据库级。授予表级别的权限适用于表和所有它的列。授予列级别的权限只适用于专用列。

·         procs_priv表适用于保存的程序。授予程序级别的权限只适用于单个程序。

管理权限(例如RELOADSHUTDOWN等等)仅在user表中被指定。这是因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由在其他授权表中列出这样的权限。事实上,只需要查询user表来决定你是否执行一个管理操作。

FILE权限也仅在user表中指定。它不是管理性权限,但你在服务器主机上读或写文件的能力与你正在存取的数据库无关。

mysqld服务器启动时,将授权表的内容读入到内存中。你可以通过FLUSH PRIVILEGES语句或执行mysqladmin flush-privilegesmysqladmin reload命令让它重新读取表。对授权表的更改生效在5.7.7节,“权限更改何时生效”描述。

当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一个好主意。要检查给定账户的权限,使用SHOW GRANTS语句。例如,要检查HostUser值分别为pc84.example.combob的账户所授予的权限,应通过语句:

 

mysql> SHOW GRANTS FOR 'bob'@'pc84.example.com';

一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给MySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意:mysqlaccess仅用userdbhost表检查存取。它不检查tables_privcolumns_privprocs_priv表中指定的表、列和程序级权限。

对于诊断权限相关的问题的其它帮助,参见5.7.8节,“拒绝访问错误的原因。对于安全问题常规建议,参见5.6节,“一般安全问题”

关注编程学问公众号