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
的结构
授权表的内容有如下用途:
·
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
)让你确保你的存取权限实际上以你认为的方式被设置。
来源:网络 作者:不详