您的位置:首页 > 数据库 > MySQL

MySQL - 存取权限系统

2007-02-09 15:54 309 查看

6 MySQL 存取权限系统

MySQL有一个先进但非标准的安全/权限系统。本节描述它的工作原理。

6.1 权限系统做什么

MySQL权限系统的主要功能是证实连接到一台给定主机的一个用户,并且赋予该用户在一个数据库上selectinsertupdatedelete的权限。

附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如
LOAD  DATA INFILE
进行授权及管理操作的能力。

6.2 MySQL 用户名和口令

MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很多不同之处:

MySQL使用于认证目的的用户名,与Unix用户名(登录名字)或Windows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用
-u
--user
选项指定一个不同的名字,这意味着无论如何你不能使得一个数据库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。

MySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。

MySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使用在那台机器上存取一个数据库的口令之间没有必要有关联。

MySQL加密口令使用了一个Unix登录期间所用的不同算法,见7.4.12 杂项函数一节中描述
PASSWORD()
ENCRYPT()
函数部分。

6.3 与MySQL服务器连接

当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定连接参数:你想要联接的主机、你的用户名和你的口令。例如,
mysql
客户可以象这样启动(可选的参数被包括在“[”和“]”之间):

shell> mysql [-h host_name][-u user_name][-pyour_pass ]

-h
,
-u
-p
选项的另一种形式是
--host=host_name
--user=user_name
--password=your_pass
。注意在
-p
--password=
与跟随它后面的口令之间没有空格。

注意:在命令行上指定一个口令是不安全的!随后在你系统上的任何用户可以通过打类似这样的命令发现你的口令:
ps  auxww
。见4.15.4 选项文件

对于命令行没有的联接参数,
mysql
使用缺省值:

缺省主机名是
localhost


缺省用户名是你的Unix登录名。

如果没有
-p
,则没有提供口令。

这样, 对一个Unix用户
joe
,下列命令是等价的:

shell>mysql -h localhost -u joe
shell>mysql -h localhost
shell>mysql -u joe
shell>mysql

其它MySQL客户程序有同样表现。

在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这可以有很多方法做到:

你能在你的主目录下“.my.cnf”的配置文件的
[client]
小节里指定连接参数。文件的相关小节看上去可能像这样:
[client]
host=host_name
user=user_name
password=your_pass

4.15.4 选项文件

你可以用环境变量指定连接参数。主机可用
MYSQL_HOST
指定,MySQL用户名字可用
USER
指定(仅对 Windows),口令可用
MYSQL_PWD
指定(但是这不安全,见下一节) 。

如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量指定的值。

6.4 使你的口令安全

以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法的风险评估:

使用一个在命令行上
-pyour_pass
--password=your_pass
的选项。这很方便但是不安全,因为你的口令对系统状态程序(例如
ps
)变得可见,它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可见的。)

使用一
个-p
--password
选项(没有指定
your_pass
值)。在这种情况下,客户程序请求来自终端的口令:
shell>mysql - u  user_name - p
Enter password: ********

客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见它。因为它对其他用户不可见, 与在命令行上指定它相比,这样进入你的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程序是合适的。如果你想要从非交互式运行的一个脚本调 用一个客户,就没有从终端输入入口令的机会。

在一个配置文件中存储你的口令。例如,你可你的主目录的“.my.cnf”文件中的
[client]
节列出你的口令:
[client]
password=your_pass

如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或可写的。保证文件的存取模式是
400
600
。见4.15.4 选项文件

你可在
MYSQL_PWD
环境变量中存储口令,但是这个方法必须想到是极不安全的且应该不使用。
ps
的某些版本包括显示运行进程的环境的选项;如果你设定
MYSQL_PWD
,你的口令将对所有人是显而易见的,甚至在没有这样一个版本的
ps
系统上,假设没有其他方法观察到进程环境是不明智的。

总之,最安全的方法是让客户程序提示口令或在一个适当保护的“.my.cnf”文件中指定口令。

6.5 MySQL提供的权限

权限信息用
user
db
host
tables_priv
columns_priv
表被存储在
mysql
数据库中(即在名为
mysql
的数据库中)。在MySQL启动时和在6.9 权限修改何时生效所说的情况时,服务器读入这些数据库表内容。

本手册所用的涉及由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表列名称和每个权限有关的上下文:

权限 上下文
select
Select_priv
insert
Insert_priv
update
Update_priv
delete
Delete_priv
index
Index_priv
alter
Alter_priv
create
Create_priv
数据库、表或索引
drop
Drop_priv
数据库或表
grant
Grant_priv
数据库或表
references
References_priv
数据库或表
reload
Reload_priv
服务器管理
shutdown
Shutdown_priv
服务器管理
process
Process_priv
服务器管理
file
File_priv
在服务器上的文件存取
selectinsertupdatedelete权限允许你在一个数据库现有的表上实施操作。

SELECT
语句只有在他们真正从一个表中检索行是才需要select权限,你可以执行某个
SELECT
语句,甚至没有任何到服务器上的数据库里的存取任何东西的许可。例如,你可使用
mysql
客户作为一个简单的计算器:

mysql> SELECT 1+1;
mysql> SELECT PI()*2;

index权限允许你创建或抛弃(删除)索引。

alter权限允许你使用
ALTER TABLE


createdrop权限允许你创建新的数据库和表,或抛弃(删除)现存的数据库和表。

注意:如果你将
mysql
数据库的drop权限授予一个用户,该用户能抛弃存储了MySQL存取权限的数据库!

grant权限允许你把你自己拥有的那些权限授给其他的用户。

file权限给予你用
LOAD DATA INFILE
SELECT ...  INTO OUTFILE
语句读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务器能读或写的任何文件。

其余的权限用于管理性操作,它使用
mysqladmin
程序实施。下表显示
mysqladmin
支配每个管理性权限允许你执行的命令:

优惠 权限拥有者允许执行的命令
reload
reload
,
refresh
,
flush-privileges
,
flush-hosts
,
flush-logs
,
flush-tables
shutdown
shutdown
precess
processlist
,
kill
reload
命令告诉服务器再读入授权表,
refresh
命令清洗所有表并打开和关闭记录文件,
flush-privileges
reload
的一个同义词,其它
flush-*
命令执行类似
refresh
的功能,但是范围更有限,并且在某些情况下可能更好用。例如,如果你只是想清洗记录文件,
flush-logs
refresh
是更好的选择。

shutdown
命令关掉服务器。

processlist
命令显示在服务器内执行的线程的信息。
kill
命令杀死服务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来显示或杀死其他用户启动的线程。

总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你应该在授予某个权限时试验特定的警告:

grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并有grant权限的用户可以合并权限。

alter权限可以用于通过重新命名表来推翻权限系统。

file权限可以被滥用在服务器上读取任何世界可读(world-readable,即任何人可读)的文件到一张数据库表,然后其内容能用
SELECT
被存取。

shutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务, 。

precess权限能被用来察看当前执行的查询的普通文本,包括设定或改变口令查询。

mysql
数据库上的权限能被用来改变口令和其他存取权限信息。(口令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够的权限,同一个用户能用不同的一个代替一个口令。)

有一些事情你不能用MySQL权限系统做到:

你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹配一个用户并且然后拒绝连接。

你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建或抛弃数据库本身。

6.6 权限系统工作原理

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
表,在这些授权表中字段如下:

表名称
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
Reload_priv
Shutdown_priv
Process_priv
File_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
每个授权表包含范围字段和权限字段。

范围字段决定表中每个条目的范围,即,条目适用的上下文。例如, 一个
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
表包含范围字段,指出每个条目适用的表或表/列的组合。

对于检查存取的用途,比较
Host
值是忽略大小写的。
User
Passwor
d、
Db
Table_name
值是区分大小写的。
Column_name
值在MySQL3.22.12或以后版本是忽略大小写的。

权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规则在6.8 存取控制, 阶段2:请求证实描述。

范围字段是字符串,如下所述;每个字段的缺省值是空字符串:

字段名 类型
Host
CHAR(60)
User
CHAR(16)
Password
CHAR(16)
Db
CHAR(64)
(
tables_priv
columns_priv
表为
CHAR(60)
user
db
host
表中,所有权限字段被声明为
ENUM('N','Y')
--每一个都可有值
'N'
'Y'
,并且缺省值是
'N'
.

tables_priv
columns_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'
简单地说,服务器使用这样的授权表:

user
表范围字段决定是否允许或拒绝到来的连接。对于允许的连接,权限字段指出用户的全局(超级用户)权限。

db
host
表一起使用:

db
表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定允许哪个操作。

当你想要一个给定的
db
条目应用于若干主机时,
host
表作为
db
表的扩展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个数据库,在用户的
db
表的
Host
条目设为空值,然后将那些主机的每一个移入
host
表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实

tables_priv
columns_priv
表类似于
db
表,但是更精致:他们在表和列级应用而非在数据库级。

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

file权限也仅在
user
表中指定。它不是管理性权限,但你读或谢在服务器主机上的文件的的能力独立于你正在存取的数据库。

mysqld
服务器启动时,读取一次授权表内容。对授权表的更改生效在6.9 权限更改何时生效描述。

当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一个好主意。为帮助诊断问题,见6.13 “存取拒绝引起
错误的原因
。对于安全问题上的忠告,见6.14 怎么对使MySQL安全对抗解密高手

一个有用的诊断工具是
mysqlaccess
脚本,由Carlier Yves 提供给MySQL分发。使用
--help
选项调用
mysqlaccess
查明它怎样工作。注意:
mysqlaccess
仅用
user
db
host
表仅检查存取。它不检查表或列级权限。

6.7 存取控制, 阶段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
条目的值的组合如何应用于到来的连接:

Host
User
被条目匹配的连接
'thomas.loc.gov'
'fred'
fred
, 从
thomas.loc.gov
连接
'thomas.loc.gov'
''
任何用户, 从
thomas.loc.gov
连接
'%'
'fred'
fred
, 从任何主机连接
'%'
''
任何用户, 从任何主机连接
'%.loc.gov'
'fred'
fred
, 从在
loc.gov
域的任何主机连接
'x.y.%'
'fred'
fred
, 从
x.y.net
x.y.com
,
x.y.edu
等联接。(这或许无用)
'144.155.166.177'
'fred'
fred
, 从
有144.155.166.177
IP 地址的主机连接
'144.155.166.%'
'fred'
fred
, 从
144.155.166
C类子网的任何主机连接
既然你能在
Host
字段使用IP通配符值(例如,
'144.155.166.%'
匹配在一个子网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机为
144.155.166.somewhere.com
。为了阻止这样的企图,MySQL不允许匹配以数字和一个点起始的主机名,这样,如果你用一个命名为类似
1.2.foo.com
的主机,它的名字决不会匹配授权表中
Host
列。只有一个IP数字能匹配IP通配符值。

一个到来的连接可以被在
user
表中的超过一个条目匹配。例如,一个由
fred
thomas.loc.gov
的连接匹配多个条目如上所述。如果超过一个匹配,服务器怎么选择使用哪个条目呢?服务器在启动时读入
user
表后通过排序来解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一个匹配的条目被使用。

user
表排序工作如下,假定
user
表看起来像这样:

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| %         |root     | ...
| %         | jeffrey  | ...
| localhost |root     | ...
| localhost |          | ...
+-----------+----------+-

当服务器在表中读取时,它以最特定的
Host
值为先的次序排列(
'%'
Host
列里意味着“任何主机”并且是最不特定的)。有相同
Host
值的条目以最特定的
User
值为先的次序排列(一个空白
User
值意味着“任何用户”并且是最不特定的)。最终排序的
user
表看起来像这样:

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| localhost |root     | ...
| localhost |          | ...
| %         | jeffrey  | ...
| %         |root     | ...
+-----------+----------+-

当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹配。对于由
jeffrey
localhost
的一个连接,在
Host
列的
'localhost'
条目首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。(
'%'/'jeffrey'
条目也将匹配,但是它不是在表中的第一匹配。)

这是另外一个例子。假定
user
桌子看起来像这样:

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| %              | jeffrey  | ...
| thomas.loc.gov |          | ...
+----------------+----------+-

排序后的表看起来像这样:

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| thomas.loc.gov |          | ...
| %              | jeffrey  | ...
+----------------+----------+-

一个由
jeffrey
thomas.loc.gov
的连接被第一个条目匹配,而一个由
jeffrey
whitehouse.gov
的连接被第二个匹配。

普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。先前的例子说明了这点,在那里一个由
jeffrey
thomas.loc.gov
的连接没被包含
'jeffrey'
作为
User
字段值的条目匹配,但是由没有用户名的题目匹配!

如果你有服务器连接的问题,打印出
user
表并且手工排序它看看第一个匹配在哪儿进行。

6.8 存取控制,阶段2:请求证实

一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子
user
db
host
tables_priv
columns_priv
表的任何一个。授权表用
GRANT
REVOKE
命令操作。见7.26
GRANT
REVOKE
句法
。(你可以发觉参考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。)

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
字段可以包含通配符,但排序更简单。

请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是不同于使解释更简单。)

对管理请求(shutdownreload等等),服务器仅检查
user
表条目,因为那是唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。例如,如果你想要执行
mysqladmin  shutdown
,但是你的
user
表条目没有为你授予shutdown权限,存取甚至不用检查
db
host
表就被拒绝。(因为他们不包含
Shutdown_priv
行列,没有这样做的必要。)

对数据库有关的请求(insertupdate等等),服务器首先通过查找
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
语句,你就都要insertselect权限。你的权限必须如此以便
user
表条目授予一个权限而
db
表条目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把两个表区别开来;两个条目授予的权限必须组合起来。

host
表能被用来维护一个“安全”服务器列表。在TcX,
host
表包含一个在本地的网络上所有的机器的表,这些被授予所有的权限。

你也可以使用
host
表指定不安全的主机。假定你有一台机器
public.your.domain
,它位于你不认为是安全的一个公共区域,你可以用下列的
host
表条目子允许除了那台机器外的网络上所有主机的存取:

+--------------------+----+-
| Host               | Db | ...
+--------------------+----+-
| public.your.domain | %  | ... (所有权限设为 'N')
| %.your.domain      | %  | ... (所有权限设为 'Y')
+--------------------+----+-

当然,你应该总是测试你在授权表中的条目(例如,使用
mysqlaccess
)让你确保你的存取权限实际上以你认为的方式被设置。

6.9 权限更改何时生效

mysqld
启动时,所有的授权表内容被读进存储器并且从那点生效。

GRANT
、REVOKE或
SET PASSWORD
对授权表施行的修改会立即被服务器注意到。

如果你手工地修改授权表(使用
INSERT
、UPDATE等等),你应该执行一个
FLUSH  PRIVILEGES
语句或运行
mysqladmin flush-privileges
告诉服务器再装载授权表,否则你的改变将不生效,除非你重启服务器。

当服务器注意到授权表被改变了时,现存的客户连接有如下影响:

表和列权限在客户的下一次请求时生效。

数据库权限改变在下一个
USE db_name
命令生效。

全局权限的改变和口令改变在下一次客户连接时生效。

6.10 建立初始的MySQL权限

在安装MySQL后,你通过运行
scripts/mysql_install_db
安装初始的存取权限。见4.7.1 快速安装概述
scripts/mysql_install_db
脚本启动
mysqld
服务器,然后初始化授权表,包含下列权限集合:

MySQL
root
用户作为可做任何事情的一个超级用户被创造。连接必须由本地主机发出。注意:出世的
root
口令是空的,因此任何人能以
root
而没有一个口令进行连接并且被授予所有权限。

一个匿名用户被创造,他可对有
一个'test'
或以
'test_'
开始的名字的数据库做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视为匿名用户。

其他权限被拒绝。例如,一般用户不能使用
mysqladmin shutdown
mysqladmin      processlist


注意:对Win32的初始权限是不同的。见4.12.4 在Win32上运行MySQL

既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL
root
用户指定一个口令。你可以做如下(注意,你使用
PASSWORD()
函数指定口令):

shell> mysql -uroot mysql
mysql> UPDATE user SET Password=PASSWORD('new_password')
WHERE user='root';
mysql> FLUSH PRIVILEGES;

MySQL 3.22和以上版本中,你可以使用
SET PASSWORD
语句:

shell> mysql -uroot mysql
mysql> SET PASSWORD FORroot=PASSWORD('new_password');

设置口令的另一种方法是使用
mysqladmin
命令:

shell> mysqladmin -uroot password new_password

注意:如果你使用第一种方法在
user
表里直接更新口令,你必须告诉服务器再次读入授权表(用
FLUSH  PRIVILEGES
),因为否则改变将不被注意到。

一旦
root
口令被设置,此后当你作为
root
与服务器连接时,你必须供应那个口令。

你可能希望让
root
口令为空白以便当你施行附加的安装时,你不需要指定它或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。

看看
scripts/mysql_install_db
脚本,看它如何安装缺省的权限。你可用它作为一个研究如何增加其他用户的基础。

如果你想要初始的权限不同于上面描述的那些,在你运行
mysql_install_db
之前,你可以修改它。

为了完全重建权限表,删除在包含
mysql
数据库的目录下所有“*.frm”,“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,当你运行
mysqld  --help
时,它被列出。)然后运行
mysql_install_db
脚本,可能在首先编辑它拥有你想要的权限之后。

注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果你偶然做了,你应该在运行
mysql_install_db
之前你的MySQL分发中拷回它们。

6.11 向MySQL增加新用户权限

你可以有2个不同的方法增加用户:通过使用
GRANT
语句或通过直接操作MySQL授权表。比较好的方法是使用
GRANT
语句,因为他们是更简明并且好像错误少些。

下面的例子显示出如何使用
mysql
客户安装新用户。这些例子假定权限根据以前的章节描述的缺省被安装。这意味着为了改变,你必须在
mysqld
正在运行同一台机器上,你必须作为MySQL
root
用户连接,并且
root
用户必须对
mysql
数据库有insert权限和reload管理权限。另外,如果你改变了
root
用户口令,你必须如下的
mysql
命令指定它。

你可以通过发出
GRANT
语句增加新用户:

shell> mysql --user=root mysql
mysql>GRANT ALL PRIVILEGES ON *.* TO monty@localhost
IDENTIFIED BY 'something' WITHGRANT OPTION;
mysql>GRANT ALL PRIVILEGES ON *.* TO monty@"%"
IDENTIFIED BY 'something' WITHGRANT OPTION;
mysql>GRANT RELOAD,PROCESS ON *.* TO admin@localhost;
mysql>GRANT USAGE ON *.* TO dummy@localhost;

这些
GRANT
语句安装3个新用户:

monty
可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个口令(
'something'
做这个。注意,我们必须对
monty@localhost
monty@"%"
发出
GRANT
语句。如果我们增加
localhost
条目,对
localhost
的匿名用户条目在我们从本地主机连接接时由
mysql_install_db
创建的条目将优先考虑,因为它有更特定的
Host
字段值,所以以
user
表排列顺序看更早到来。
admin
可以从
localhost
没有一个口令进行连接并且被授予reloadprocess管理权限的用户。这允许用户执行
mysqladmin      reload
mysqladmin refresh
mysqladmin flush-*
命令,还有
mysqladmin      processlist
。没有授予数据库有关的权限。他们能在以后通过发出另一个
GRANT
语句授权。
dummy
可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设置为
'N'
--
USAGE
权限类型允许你无需权限就可设置一个用户。它假定你将在以后授予数据库相关的权限。
你也可以直接通过发出
INSERT
语句增加同样的用户存取信息,然后告诉服务器再次装入授权表:

shell> mysql --user=root mysql
mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD('something'),
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y')
mysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'),
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y')
mysql> INSERT INTO user SET Host='localhost',User='admin',
Reload_priv='Y', Process_priv='Y';
mysql> INSERT INTO user (Host,User,Password)
VALUES('localhost','dummy','');
mysql> FLUSH PRIVILEGES;

取决于你的MySQL版本,对上述,你可能必须使用一个不同数目
'Y'
值(在3.22.11以前的版本有更少的权限列)。对
admin
用户,只用在3.22.11开始的版本具有的更加可读的
INSERT
扩充的语法。

注意,为了设置一个超级用户,你只需创造一个
user
表条目,其权限字段设为
'Y'
。不需要
db
host
表的条目。

user
表中的权限列不是由最后一个
INSERT
语句明确设置的(对
dummy
用户),因此那些列被赋予缺省值
'N'
。这是
GRANT  USAGE
做的同样的事情。

下列例子增加一个用户
custom
,他能从主机
localhost
server.domain
whitehouse.gov
连接。他只想要从
localhost
存取
bankaccount
数据库,从
whitehouse.gov
存取
expenses
数据库和从所有3台主机存取
customer
数据库。他想要从所有3台主机上使用口令
stupid


为了使用
GRANT
语句设置个用户的权限,运行这些命令:

shell> mysql --user=root mysql
mysql>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON bankaccount.*
TO custom@localhost
IDENTIFIED BY 'stupid';
mysql>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON expenses.*
TO custom@whitehouse.gov
IDENTIFIED BY 'stupid';
mysql>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON customer.*
TO custom@'%'
IDENTIFIED BY 'stupid';

通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时
FLUSH  PRIVILEGES
):

shell> mysql --user=root mysql
mysql> INSERT INTO user (Host,User,Password)
VALUES('localhost','custom',PASSWORD('stupid'));
mysql> INSERT INTO user (Host,User,Password)
VALUES('server.domain','custom',PASSWORD('stupid'));
mysql> INSERT INTO user (Host,User,Password)
VALUES('whitehouse.gov','custom',PASSWORD('stupid'));
mysql> INSERT INTO db
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
Create_priv,Drop_priv)
VALUES
('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
Create_priv,Drop_priv)
VALUES
('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
Create_priv,Drop_priv)
VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y');
mysql> FLUSH PRIVILEGES;

头3个
INSERT
语句增加
user
表条目,允许用户
custom
用给定口令从不同的主机进行连接,但是没有授予任何许可(所有权限被设置为缺省值
'N'
)。后3个
INSERT
语句增加
db
表条目,授予
custom
bankaccount
expenses
customer
数据库权限,但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告知再次装入他们(用
FLUSH  PRIVILEGES
)以便使权限修改生效。

如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发出一个如下的
GRANT
语句:

mysql>GRANT ...
ON *.*
TO myusername@"%.mydomainname.com"
IDENTIFIED BY 'mypassword';

为了通过直接修改授权表做同样的事情,这样做:

mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername',
PASSWORD('mypassword'),...);
mysql> FLUSH PRIVILEGES;

你也可以使用
xmysqladmin
mysql_webadmin
甚至
xmysql
在授权表中插入、改变和更新值。你可以在MySQLContrib目录找到这些实用程序。

6.12 怎样设置口令

在前面小节的例子里说明了一个重要的原则:当你使用
INSERT
UPDATE
语句存储一个非空的口令时,你必须使用
PASSWORD()
函数加密它。这是因为在
user
表中以加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图设置口令:

shell> mysql -uroot mysql
mysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey','biscuit');
mysql> FLUSH PRIVILEGES

结果是纯文本值
'biscuit'
作为口令被存储在
user
表中。在用户
jeffrey
试图用这个口令连接服务器时,
mysql
客户用
PASSWORD()
加密它并且将结果送给服务器,服务器比较在
user
表中的值(它是纯文本值
'biscuit'
)和加密的口令(而不是
'biscuit'
),比较失败并且服务器拒绝连接:

shell> mysql -u jeffrey -pbiscuit test
Access denied

因为当他们被插入
user
表时,口令必须被加密,
相反,INSERT
语句应该象这样被指定:

mysql> INSERT INTO user (Host,User,Password)
VALUES('%','jeffrey',PASSWORD('biscuit'));

当你使用
SET PASSWORD
语句时,你也必须使用
PASSWORD()
函数:

mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');

如果你使用
GRANT ... IDENTIFIED BY
语句或
mysqladmin password
命令设置口令,
PASSWORD()
函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指定一个口令
'biscuit'


mysql>GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';



shell> mysqladmin -u jeffrey password biscuit

注意:
PASSWORD()
不是以在Unix口令加密的同样方法施行口令加密。你不应该假定如果你的Unix口令和你的MySQL口令是一样的,
PASSWORD()
将导致与在Unix口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令

6.13
Access denied
错误的原因

当你试着联接MySQL服务器时,如果你碰到
Access  denied
错误,显示在下面的表指出一些你能用来更正这个问题的动作:

你是在安装MySQL以后运行
mysql_install_db
的脚本,来设置初始授权表内容吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初始权限:
shell> mysql -uroot test

服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此
PATH
MySQL安装根目录的路径。

在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可:
shell> mysql -uroot mysql

服务器应该让你连接,因为MySQL
root
用户初始时没有口令。既然那也是一个安全风险,当你正在设置其他MySQL用户时,设定
root
口令是一件重要的事请。如果你作为
root
尝试连接并且得到这个错误:

Access denied for user: '@unknown' to database mysql

这意味着,你没有一个条目在
user
表中的一个
User
列值为
'root'
并且
mysqld
不能为你的客库解析主机名。在这种情况下,你必须用
--skip-grant-tables
选项重启服务器并且编辑你的“/etc/hosts”或“/windows/hosts”文件为你的主机增加一个条目。

如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以后版本,你运行了
mysql_fix_privilege_tables
脚本吗?如果没有,运行它。在
GRANT
语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。

如果你直接对授权表做修改(使用
INSERT
UPDATE
语句)并且你的改变似乎被忽略,记住,你必须发出一个
FLUSH      PRIVILEGES
语句或执行一个
mysqladmin flush-privileges
命令导致服务器再次读入表,否则你的改变要道下一次服务器被重启时再生效。记住在你设定
root
口令以后,你将不需要指定它,直到在你清洗(flush)权限以后,因为服务器仍然不会知道你改变了口令!

如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权限改变何时生效小节所述。

为了测试,用
--skip-grant-tables
选项启动
mysqld
守护进程,然后你可以改变MySQL授权表并且使用
mysqlaccess
脚本检查你的修改是否有如期的效果。当你对你的改变满意时,执行
mysqladmin      flush-privileges
告诉
mysqld
服务器开始使用新的权限表。注意:再次装入授权表覆盖了
--skip-grant-tables
选项。这允许你告诉服务器开始使用授权表,而不用停掉并重启它。

如果你有一个Perl、Python或ODBC程序的存取问题,试着用
mysql -u      user_name db_name
mysql -u user_name -pyour_pass db_name
与服务器连接。如果你能用
mysql
客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在
-p
和口令之间没有空格;你也能使用
--password=your_pass
句法指定口令。)

如果你不能让口令工作,记得如果你用
INSERT
,
UPDATE
SET      PASSWORD
语句设置口令,你必须使用
PASSWORD()
函数。如果你用
GRANT      ... INDENTIFIED BY
语句或
mysqladmin password
命令指定口令,
PASSWORD()
函数是不需要的。见6.12 怎样设置口令

localhost
是你本地主机名的一个同义词,并且也是如果你不明确地指定主机而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系统上,连接
localhost
是不行的(
localhost
连接使用Unix套接字进行,它没被 MIT-pthreads支持),为了在这样的系统上避免这个问题,你应该使用
--host
选项明确地命名服务器主机,这将做一个 TCP/IP连接到
mysqld
服务器。在这种情况下,你必须有在服务器主机上的
user
表中条目的你真实的主机名。(即使你在服务器同一台的主机上运行一个客户程序,这也是真的。)

当尝试用
mysql -u user_name db_name
与数据库连接时,如果你得到一个
Access      denied
错误,你可能有与
user
桌有关的问题,通过执行
mysql      -uroot mysql
并且发出下面的SQL语句检查:
mysql> SELECT * FROM user;

结果应该包含一个有
Host
User
列的条目匹配你的计算机主机名和你的MySQL用户名。

Access denied
错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在
user
表中有一个条目,正确地匹配在错误消息给出的主机名和用户名。

如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列错误,那么在
user
表中没有匹配那台主机行:
Host ... is not allowed to connect to this MySQL server

你可以通过使用
mysql
命令行工具(在服务器主机上!)修正它,把你正在试图连接的用户/主机名组合新加一行到
user
表中。如果你不在运行MySQL 3.22并且你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个
'%'
条目作为
Host
列值放在
user
表中并且在服务器机器上使用
--log
选项重启
mysqld
。在试图从客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。(然后用在记录文件上面显示出的实际的主机名代替
user
表中的
'%'
条目。否则,你将有一个不安全的系统。)

如果
mysql -uroot test
工作但是
mysql -h your_hostname -uroot      test
导致
Access denied
,那么在
user
表中你可能没有你的主机的正确名字。这里的一个普遍的问题是在
user
表条目中的
Host
值指定一个唯一的主机名,但是你系统的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在
user
表中有一个主机是
'tcx'
的条目,但是你的 DNS告诉MySQL你的主机名是
'tcx.subnet.se'
,条目将不工作。尝试把一个条目加到
user
表中,它包含你主机的IP数字作为
Host
列的值。(另外,你可以把一个条目加到
user
表中,它有包含一个通配符如
'tcx.%'
Host
值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)

如果
mysql -u user_name test
工作但是
mysql -u user_name      other_db_name
不工作,对
other_db_name
,你在
db
表中没有没有一个条目列出。

当在服务器机器上执行
mysql -u user_name db_name
时,它工作,但是在其它客户机器上执行
mysql      -h host_name -u user_name db_name
时,它却不工作,你没有把客户机器列在
user
表或
db
表中。

如果你不能弄明白你为什么得到
Access denied
,从
user
表中删除所有
Host
包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用
Host
=
'%'
User
=
'some      user'
插入一个新条目,认为这将允许你指定
localhost
从同一台机器进行连接。它不工作的原因是缺省权限包括一个有
Host
=
'localhost'
User
=
''
的条目,因为那个条目一个比
'%'
更具体的
Host
'localhost'
,当从
localhost
连接时,它用于指向新条目!正确的步骤是插入
Host
=
'localhost'
User
=
'some_user'
的第2个条目,或删除
Host
=
'localhost'
User
=
''
条目。

如果你得到下列错误,你可以有一个与
db
host
表有关的问题:
Access to database denied

如果从
db
表中选择了在
Host
列有空值的条目,保证在
host
表中有一个或多个相应的条目,指定运用
db
表中的哪些主机。如果在使用SQL命令
SELECT      ... INTO OUTFILE
LOAD DATA INFILE
时,你得到错误,在
user
表中的你的条目可能启用file权限。

记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数,检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。见4.15.4 选项文件。如果当你没有任何选项运行一个客户时,你得到
Access      denied
,确认你没在任何选项文件里指定一个旧的口令!见4.15.4 选项文件

如果任何其它事情失败,用调试选项(例如,
--debug=d,general,query
)启动
mysqld
守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每个命令的信息。见G.1 调试一个MySQL服务器

如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用
mysqldump      mysql
命令倾倒数据库表。象平时一样,用
mysqlbug
脚本邮寄你的问题。在一些情况下你可能用
--skip-grant-tables
重启
mysqld
以便能运行
mysqldump


6.14 怎样使MySQL安全以对抗解密高手

当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文在连接上传输。

所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全,你应该安装
ssh
(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服务器与一个MySQL客户之间得到一个加密的TCP/IP连接。

为了使一个MySQL系统安全,强烈要求你考虑下列建议:

对所有MySQL用户使用口令。记住,如果
other_user
没有口令,任何人能简单地用
mysql      -u other_user db_name
作为任何其它的人登录。对客户机/服务器应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通过编辑
mysql_install_db
脚本改变所有用户的口令,或仅仅MySQL
root
的口令,象这样:
shell> mysql -uroot mysql
mysql> UPDATE user SET Password=PASSWORD('new_password')
WHERE user='root';
mysql> FLUSH PRIVILEGES;


不要作为Unix的
root
用户运行MySQL守护进程。
mysqld
能以任何用户运行,你也可以创造一个新的Unix用户
mysql
使一切更安全。如果你作为其它Unix用户运行
mysqld
,你不需要改变在
user
表中的
root
用户名,因为MySQL用户名与Unix 用户名没关系。你可以作为其它Unix用户编辑
mysql.server
启动脚本
mysqld
。通常这用
su
命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行MySQL

如果你把一个Unix
root
用户口令放在
mysql.server
脚本中,确保这个脚本只能对
root
是可读的。

检查那个运行
mysqld
的Unix用户是唯一的在数据库目录下有读/写权限的用户。

不要把process权限给所有用户。
mysqladmin processlist
的输出显示出当前执行的查询正文,如果另外的用户发出一个
UPDATE      user SET password=PASSWORD('not_secure')
查询,被允许执行那个命令的任何用户可能看得到。
mysqld
为有process权限的用户保留一个额外的连接, 以便一个MySQL
root
用户能登录并检查,即使所有的正常连接在使用。

不要把file权限给所有的用户。有这权限的任何用户能在
拥有mysqld
守护进程权限的文件系统那里写一个文件!为了使这更安全一些,用
SELECT      ... INTO OUTFILE
生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文件。这可能被滥用,例如,通过使用
LOAD      DATA
装载“/etc/passwd”进一个数据库表,然后它能用
SELECT
被读
入。


如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则上讲,
--secure
选项对
mysqld
应该使主机名更安全。在任何情况下,你应该非常小心地使用包含通配符的主机名!

下列
mysqld
选项影响安全:

--secure
gethostbyname()
系统调用返回的IP数字被检查,确保他们解析回到原来的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。
--skip-grant-tables
这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数据库的权力!(通过执行
mysqladmin      reload
,你能告诉一个正在运行的服务器再次开始使用授权表。)
--skip-name-resolve
主机名不被解析。所有在授权表的
Host
的列值必须是IP数字或
localhost
--skip-networking
在网络上不允许TCP/IP连接。所有到
mysqld
的连接必须经由Unix套接字进行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不支持Unix套接字。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: