免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: luren04
打印 上一主题 下一主题

【申请加精】MySQL 5.1参考手册  关闭 [复制链接]

论坛徽章:
0
91 [报告]
发表于 2008-04-15 13:09 |只看该作者
5.7.3. MySQL提供的权限
账户权限信息被存储在mysql数据库的user、db、host、tables_priv、columns_priv和procs_priv表中。在MySQL启动时并在5.7.7节,“权限更改何时生效”所说的情况时,服务器将这些数据库表内容读入内存。

GRANT和REVOKE语句所用的涉及权限的名称显示在下表,还有在授权表中每个权限的表列名称和每个权限有关的上下文。关于每个权限的含义相关的详细信息参见13.5.1.3节,“GRANT和REVOKE语法”。

权限

上下文

CREATE
Create_priv
数据库、表或索引

DROP
Drop_priv
数据库或表

GRANT OPTION
Grant_priv
数据库、表或保存的程序

REFERENCES
References_priv
数据库或表

ALTER
Alter_priv


DELETE
Delete_priv


INDEX
Index_priv


INSERT
Insert_priv


SELECT
Select_priv


UPDATE
Update_priv


CREATE VIEW
Create_view_priv
视图

SHOW VIEW
Show_view_priv
视图

ALTER ROUTINE
Alter_routine_priv
保存的程序

CREATE ROUTINE
Create_routine_priv
保存的程序

EXECUTE
Execute_priv
保存的程序

FILE
File_priv
服务器主机上的文件访问

CREATE TEMPORARY TABLES
Create_tmp_table_priv
服务器管理

LOCK TABLES
Lock_tables_priv
服务器管理

CREATE USER
Create_user_priv
服务器管理

PROCESS
Process_priv
服务器管理

RELOAD
Reload_priv
服务器管理

REPLICATION CLIENT
Repl_client_priv
服务器管理

REPLICATION SLAVE
Repl_slave_priv
服务器管理

SHOW DATABASES
Show_db_priv
服务器管理

SHUTDOWN
Shutdown_priv
服务器管理

SUPER
Super_priv
服务器管理


当从早期的没有CREATE VIEW、SHOW VIEW、CREATE ROUTINE、ALTER ROUTINE和EXECUTE权限的版本的MySQL中升级时,要想使用这些权限,你必须使用MySQL分发提供的mysql_fix_privilege_tables脚本升级 授权表。参见2.10.2节,“升级授权表”。

如果启用了二进制记录,要想创建或修改保存的程序,你还需要SUPER权限,详细描述见20.4节,“存储子程序和触发程序的二进制日志功能”。

通过CREATE和DROP权限,你可以创建新数据库和表,或删除(移掉)已有数据库和表。如果你将mysql数据库中的DROP权限授予某用户,用户可以删掉MySQL访问权限保存的数据库。

SELECT、INSERT、UPDATE和DELETE权限允许你在一个数据库现有的表上实施操作。

SELECT语句只有在他们真正从一个表中检索行时才需要SELECT权限。一些SELECT语句不访问表,甚至没有任何到服务器上的数据库里的存取任何东西的许可。例如,你可使用mysql客户端作为一个简单的计算器来评估未引用表的表达式:

mysql> SELECT 1+1;mysql> SELECT PI()*2;INDEX权限允许你创建或删除索引。INDEX适用已有表。如果你具有某个表的CREATE权限,你可以在CREATE TABLE语句中包括索引定义。

通过ALTER权限,你可以使用ALTER TABLE来更改表的结构和重新命名表。

需要CREATE ROUTINE权限来创建保存的程序(函数和程序),ALTER ROUTINE权限来更改和删除保存的程序,EXECUTE来执行保存的程序。

GRANT权限允许你把你自己拥有的那些权限授给其他的用户。可以用于数据库、表和保存的程序。

FILE权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句读和写服务器上的文件,任何被授予FILE权限的用户都能读或写MySQL服务器能读或写的任何文件。(说明用户可以读任何数据库目录下的文件,因为服务器可以访问这些文件)。 FILE权限允许用户在MySQL服务器具有写权限的目录下创建新文件。不能覆盖已有文件。

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

权限
权限拥有者允许执行的命令

RELOAD
flush-hosts, flush-logs, flush-privileges, flush-status, flush-tables, flush-threads, refresh, reload

SHUTDOWN
shutdown

PROCESS
processlist

SUPER
kill


reload命令告诉服务器将授权表重新读入内存。flush-privileges是reload的同义词,refresh命令清空所有表并打开并关闭记录文件,其它flush-xxx命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更好用。例如,如果你只是想清空记录文件,flush-logs比refresh是更好的选择。

shutdown命令关掉服务器。只能从mysqladmin发出命令。没有相应的SQL语句。

processlist命令显示在服务器内执行的线程的信息(即其它账户相关的客户端执行的语句)。kill命令杀死服务器线程。你总是能显示或杀死你自己的线程,但是你需要PROCESS权限来显示或杀死其他用户和SUPER权限启动的线程。参见13.5.5.3节,“KILL语法”。

拥有CREATE TEMPORARY TABLES权限便可以使用CREATE TABLE语句中的关键字TEMPORARY。
拥有LOCK TABLES权限便可以直接使用LOCK TABLES语句来锁定你拥有SELECT权限的表。包括使用写锁定,可以防止他人读锁定的表。

拥有REPLICATION CLIENT权限便可以使用SHOW MASTER STATUS和SHOW SLAVE STATUS。

REPLICATION SLAVE权限应授予从服务器所使用的将当前服务器连接为主服务器的账户。没有这个权限,从服务器不能发出对主服务器上的数据库所发出的更新请求。

拥有SHOW DATABASES权限便允许账户使用SHOW DATABASE语句来查看数据库名。没有该权限的账户只能看到他们具有部分权限的数据库, 如果数据库用--skip-show-database选项启动,则根本不能使用这些语句。请注意全局权限指数据库的权限。

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

FILE权限可以被滥用于将服务器主机上MySQL能读取的任何文件读入到数据库表中。包括任何人可读的文件和服务器数据目录中的文件。可以使用SELECT访问数据库表,然后将其内容传输到客户端上。
GRANT权限允许用户将他们的权限给其他用户。有不同的权限并有GRANT权限的2个用户可以合并权限。
ALTER权限可以用于通过重新命名表来推翻权限系统。
SHUTDOWN权限通过终止服务器可以被滥用完全拒绝为其他用户服务。
PROCESS权限能被用来察看当前执行的查询的明文文本,包括设定或改变密码的查询。
SUPER权限能用来终止其它用户或更改服务器的操作方式。
授给mysql数据库本身的权限能用来改变密码和其他访问权限信息。密码被加密存储,所以恶意的用户不能简单地读取他们以知道明文密码。然而,具有user表Password列写访问权限的用户可以更改账户的密码,并可以用该账户连接MySQL服务器。
有一些事情你不能用MySQL权限系统做到:

你不能明显地指定某个给定的用户应该被拒绝访问。即,你不能明显地匹配用户然后拒绝连接。
你不能指定用户有权创建立或删除数据库中的表,但不能创建或删除数据库本身。
5.7.4. 与MySQL服务器连接
当你想要访问MySQL服务器时,MySQL客户端程序一般要求你指定参数:

·         MySQL服务器运行的主机名

·         姓名

·         密码

例如,可以从命令行按照下述提示启动MySQL客户端(用shell>表示):

shell> MySQL -h host_name -u user_name -pyour_pass-h, -u和-p选项还可以采用形式--host=host_name、--user=user_name和--password=your_pass。请注意在-p或--password=和后面的密码之间没有空格。

如果你使用-p或--password选项但没有指定密码值,客户端程序提示你输入密码。当你输入密码时并不显示密码。这比在在命令行输入密码要安全得多。系统上的任何用户可以通过命令ps auxww在命令行中指定密码。参见5.8.6节,“使你的密码安全”。

如果没有指定连接参数,MySQL客户端程序使用默认值:

默认主机名是localhost。
默认用户名在Windows中是ODBC,在Unix中是你的Unix登录名。
·         如果没有-p,则不提供密码。

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

shell> MySQL -h localhost -u joeshell> MySQL -h localhostshell> MySQL -u joeshell> MySQL其它MySQL客户端程序类似。

当进行连接时,你可以指定要使用的不同的默认值,这样不必每次在你调用客户端程序是在命令行上输入它们。这可以有很多方法做到:

你可以在选项文件的[client]小节里指定连接参数。文件的相关小节看上去可能像这样:
·                [client]·                host=host_name·                user=user_name·                password=your_pass在4.3.2节,“使用选项文件”中详细讨论了选项文件。

你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL用户名可用USER指定(仅对Windows和NetWare),密码可用MYSQL_PWD指定,尽管这不安全;参见5.8.6节,“使你的密码安全”。变量参见附录F:环境变量。
5.7.5. 访问控制, 阶段1:连接核实
当你试图连接MySQL服务器时,服务器基于你的身份以及你是否能通过供应正确的密码验证身份来接受或拒绝连接。如果不是,服务器完全拒绝你的访问,否则,服务器接受连接,然后进入阶段2并且等待请求。

你的身份基于2个信息:

你从那个主机连接
你的MySQL用户名
身份检查使用3个user表(Host, User和Password)范围列执行。服务器只有在user表记录的Host和User列匹配客户端主机名和用户名并且提供了正确的密码时才接受连接。

在user表Host值的指定方法:

Host值可以是主机名或IP号,或'localhost'指出本地主机。
你可以在Host列值使用通配符字符“%”和“_”。
Host值'%'匹配任何主机名,空Host值等价于'%'。它们的含义与LIKE操作符的模式匹配操作相同。例如,'%'的Host值与所有主机名匹配,而'%.mysql.com'匹配mysql.com域的所有主机。
·         对于指定为IP号的Host值,你可以指定一个网络掩码,说明使用多少位地址位来评比网络号。例如:

·                mysql> GRANT ALL PRIVILEGES ON db.*·                    -> -> TO david@'192.58.197.0/255.255.255.0';允许david从任何客户端用IP号client_ip来连接,下面的条件为真:

client_ip & netmask = host_ipThat is, for the GRANT statement just shown:

client_ip & 255.255.255.0 = 192.58.197.0满足该条件并可以连接MySQL服务器的IP号的范围为192.58.197.0到192.58.197.255。

·         注释:网络掩码只用来告诉服务器使用8、16、24或32位地址,例如:

·                192.0.0.0/255.0.0.0(192 A类网络的任何地址)·                192.168.0.0/255.255.0.0(192.168 A类网络的任何地址)·                192.168.1.0/255.255.255.0(192.168.1 C类网络的任何地址)·                192.168.1.1(只有该IP)下面的网络掩码(28 位)无效:

192.168.0.1/255.255.255.240·         db表记录中的空Host值表示它的权限应结合匹配客户端名的host表中的行使用。通过AND(相与)而不是或(联合)操作将权限组合到一起。你可以从5.7.6节,“访问控制, 阶段2:请求核实”找到关于host表的详细信息。

其它grant表的空Host值与'%'相同。

既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的主机,它的名字决不会匹配授权表中的Host列。只有一个IP数字能匹配IP通配符值。

通配符字符在User列中不允许,但是你能指定空的值,它匹配任何名字。如果user表匹配的连接有一个空用户名,用户被认为是匿名用户(没有名字的用户),而非客户端实际指定的名字。这意味着一个空的用户名被用于在连接期间的进一步的访问检查(即,在阶段2期间)。

Password列可以是空的。这不是通配符,也不意味着匹配任何密码,它意味着用户必须不指定一个密码进行连接。

user表中的非空Password值代表加密的密码。MySQL不以任何人可以看的明文文本格式存储密码,相反,正在试图联接的用户提供的密码被加密(使用PASSWORD函数),在连接过程中使用加密的密码检查密码是否正确。(加密后的密码未通过连接即可实现)。从MySQL角度,加密的密码是实际密码,因此你不应让其它人访问它!特别是,绝对不要让非管理用户读mysql数据库中的表!

MySQL 5.1使用强鉴定方法(最先在MySQL 4.1中适用)在前面的版本中在连接进程中的密码保护较好。即使TCP/IP包被截取或mysql数据库 被捕获也很安全。5.7.9节,“MySQL 4.1中的密码哈希处理”中详细讨论了密码加密。

下面的例子显示出各种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类子网的任何主机连接


到来的连接中的客户端名和用户名可能与user表中的多行匹配。例如,由fred从thomas.loc.gov的连接匹配多个条目如上所述。

如果有多个匹配,服务器必须选择使用哪个条目。按照下述方法解决问题:

l        服务器在启动时读入user表后进行排序。

l        然后当用户试图连接时,以排序的顺序浏览条目

l        服务器使用与客户端和用户名匹配的第一行。

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

+-----------+----------+-| Host      | User     | …+-----------+----------+-| %         | root     | …| %         | jeffrey  | …| localhost | root     | …| localhost |          | …+-----------+----------+-当服务器读取表时,它首先以最具体的Host值排序。主机名和IP号是最具体的。'%'意味着“任何主机”并且是最不特定的。有相同Host值的条目首先以最具体的User值排序(空User值意味着“任何用户”并且是最不特定的)。最终排序的user表看起来像这样:

+-----------+----------+-| Host      | User     | …+-----------+----------+-| localhost | root     | … ...| localhost |          | … ...| %         | jeffrey  | … ...| %         | root     | … ...+-----------+----------+-当客户端试图连接时,服务器浏览排序的条目并使用找到的第一匹配。对于由jeffrey从localhost的连接,表内有两个条目匹配:Host和User值为'localhost'和''的条目,和值为'%'和'jeffrey'的条目。'localhost'条目首先匹配,服务器可以使用。

还有一个例子。假定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列值的行匹配,但是由没有用户名的题目匹配!结果是,jeffrey被鉴定为匿名用户,即使他连接时指定了用户名。

如果你能够连接服务器,但你的权限不是你期望的,你可能被鉴定为其它账户。要想找出服务器用来鉴定你的账户,使用CURRENT_USER()函数。它返回user_name@host_name格式的值,说明User和Host 值匹配user表记录。假定jeffrey连接并发出下面的查询:

mysql> SELECT CURRENT_USER();+----------------+| CURRENT_USER() |+----------------+| @localhost     |+----------------+这儿显示的结果说明user表行有空的User列值。换句话说,服务器将jeffrey视为匿名用户。

诊断鉴定问题的另一个方法是打印出user表并且手动排序它看看第一个匹配在哪儿进行。又见12.9.3节,“信息函数”。

论坛徽章:
0
92 [报告]
发表于 2008-04-15 13:10 |只看该作者
5.7.9. MySQL 4.1中的密码哈希处理
5.7.9.1. 更改应用程序密码哈希值的含义
MySQL用户账户列于mysql数据库中的user表内。每个MySQL账户指定一个密码,尽管保存在user表Password列的密码不是明文,但哈希值是从表中的记录计算的。用PASSWORD()函数来计算密码的哈希值。

MySQL在客户端/服务器通信的两个阶段使用密码:

·         如果客户端试图连接服务器,有一个初始鉴定步骤,客户必须提供一个密码,并且必须与客户想要使用的账户在user表保存的哈希值匹配。

·         客户端连接后,它可以(如果有充分的权限) 设置或更改user表内所列的账户的密码哈希值值。客户端可以通过PASSWORD()函数来生成密码哈希值,或使用GRANT或SET PASSWORD语句。

换句话说,当客户端首次试图连接时,服务器使用哈希值进行鉴定。如果连接的客户端调用PASSWORD()函数或使用GRANT或SET语句来设置或更改密码,则服务器产生哈希值。

在MySQL 4.1中密码哈希算法已经更新,提供了更好的安全性并降低了密码被截取的风险。但是,该新机制只能在MySQL 4.1(和更新版本的)服务器和客户端中使用,会产生一些兼容性问题。4.1或新客户端可以连接4.1之前的服务器,因为客户端可以同时理解旧的和新的密码哈希机制。但是,4.1之前的客户端试图连接4.1版或更新版的服务器时会遇到困难。例如,3.23版mysql客户端试图连接5.1服务器时会失败并出现下面的错误消息:

shell> mysql -h localhost -u rootClient does not support authentication protocol requestedby server; consider upgrading MySQL client出现该问题的另一个普通例子是在升级到MySQL 4.1或更新版后,试图使用旧版本的PHP mysql扩展名。(参见25.3.1节,“使用MySQL和PHP的常见问题”)。

下面讨论了新、旧密码机制之间的差别,以及如果你升级了服务器但需要为4.1版以前的客户端保持向后兼容性该怎样做。A.2.3节,“客户端不支持鉴定协议”中有更详细的信息。该信息将MySQL数据库从4.0版本或更低版升级到4.1版或更高版的PHP编程人员特别重要。

注释:该讨论对比了4.1版的行为和4.1前的行为,这儿描述的4.1中的行为实际上从4.1.1开始。MySQL 4.1.0是一个“旧”的发布,因为它的实施机制与4.1.1版和更新版中的稍有不同。在MySQL 5.0 参考手册中详细描述了4.1.0和最新版之间的差别。

在MySQL 4.1之前,用PASSWORD()函数计算的密码哈希值有16个字节长。应为:

mysql> SELECT PASSWORD('mypass');+--------------------+| PASSWORD('mypass') |+--------------------+| 6f8c114b58f2ce9e   |+--------------------+在MySQL 4.1之前,user表的Password列(保存了哈希值)也是16字节长。

在MySQL 4.1中,已经对PASSWORD()函数进行了修改,可以生成41字节的哈希值:

mysql> SELECT PASSWORD('mypass');+-------------------------------------------+| PASSWORD('mypass')                        |+-------------------------------------------+| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |+-------------------------------------------+同样,user表的Password列必须有41字节长来保存这些值:

·         如果你新安装MySQL 5.1, Password列自动为41字节长。

·         从MySQL 4.1(4.1.1或4.1系列的更新版)升级到MySQL 5.1,应不会出现相关问题,因为两个版本使用相同的密码哈希机制。如果你想要将更早版本的MySQL升级到MySQL5.1,你应先升级到4.1,然后将4.1升级到5.1。

加宽的Password列可以同时保存新、旧格式的密码哈希值。可以有两种方式确定任何给定格式的密码哈希值:

·         明显的不同之处是长度(16字节和41字节)。

·         第2个不同之处是新格式的密码哈希值都以‘*’字符开头,而旧格式的密码绝对不是。

长密码哈希值具有更好的加密属性,并且客户端根据长哈希值进行鉴定比旧的短哈希值更加安全。

短密码哈希值和长密码哈希值之间的不同之处与服务器如何使用密码进行鉴定以及如何为执行密码更改操作的连接的客户端生成密码哈希值都有关。

服务器使用密码哈希值进行鉴定的方式受Password列的宽度影响:

·         如果列较短,只用短哈希鉴定。

·         如果列较长,可以有短或长哈希值,并且服务器可以使用任何一种格式:

o        4.1之前的客户端可以连接,它们只可以使用旧的哈希机制,它们可以只鉴定有短哈希的账户。

o        4.1及以后版本的客户端可以鉴定有短哈希或长哈希的账户。

对于短哈希账户的鉴定过程,4.1和以后版本的客户端比为旧版本的客户端实际要安全得多。从安全性角度,从最低安全到最安全的梯度为:

·         4.1之前的客户端用短密码哈希值进行鉴定

·         4.1或以后版本的客户端用短密码哈希值进行鉴定

·         4.1或以后版本的客户端用长密码哈希值进行鉴定

服务器为连接的客户端生成密码哈希值的方式受Password列宽度和--old-passwords选项的影响。4.1或更新版本的服务器只有满足某个条件才生成长哈希:Password列必须足够宽以容纳长哈希值并且未给定--old-passwords选项。这些条件适合:

·         Password列必须足够宽以容纳长哈希(41字节)值。如果列没有更新,仍然为4.1之前的16字节宽,当客户端使用PASSWORD()、GRANT或SET PASSWORD执行密码更改操作时,服务器注意到长哈希不适合,只生成短哈希。如果你已经升级到4.1但还没有运行 mysql_fix_privilege_tables脚本来扩宽Password列时会出现这种行为。

·         如果Password列足够宽,则可以保存短或长密码哈希值。在这种情况下,PASSWORD()、GRANT或SET PASSWORD生成长哈希,除非 用--old-passwords选项启动服务器。该选项强制服务器生成短密码哈希值。

--old-passwords选项的目的是当服务器生成长密码哈希值时,允许你维持同4.1之前的客户端的向后兼容性。该选项不影响鉴定(4.1和以后版本的客户端仍然可以使用有长密码哈希值的账户),但它防止在密码更改操作中在user表中创建长密码哈希值。在这种情况下,该账户不能再用于4.1之前的客户端。没有--old-passwords选项,可能会出现下面的不期望的情况:

·         旧客户端连接有短密码哈希值的账户。

·         客户更改自己的密码。没有--old-passwords,可以为该账户生成长密码哈希值。

·         下次旧客户试图连接账户时不能连接上,因为账户有长密码哈希值,需要新的哈希机制进行鉴定。(一旦账户user表中为长密码哈希值,只有4.1和以后版本的客户端可以鉴定它,因为4.1之前的客户端不理解长哈希)。

该场景说明,如果你必须支持旧的4.1之前的客户端,不使用--old-passwords选项运行4.1或更新版本的服务器很危险。用--old-passwords运行服务器,密码更改操作不会生成长密码哈希值,这样旧客户端也可以访问账户。(这些客户端不能意外地因更改了密码将自己锁出去,并留下长密码哈希值)。

--old-passwords选项的不利之处是你创建或更改的密码使用短哈希,甚至对于4.1客户端也如此。这样,你丢失了长密码哈希值提供的安全性。如果你想要创建有长哈希的账户(例如,为4.1客户端),你必须不使用--old-passwords来运行服务器。

下面的场景可用于运行4.1或以后的服务器,包括MySQL 5.1:

场景1:user表中的短Password列:

·         只有短哈希可以保存到Password列。

·         服务器只使用短哈希进行客户端鉴定。

·         对于连接的客户端,调用PASSWORD()、GRANT或SET PASSWORD的密码哈希生成操作专使用短哈希。对账户的任何更改均会生成短密码哈希值。

·          --old-passwords选项可以使用但是多余,因为Password列较短,服务器只生成短密码哈希值。

场景2:长Password列;没有用--old-passwords选项启动服务器:

·         短或长哈希可以保存到Password列。

·         4.1和以后版本的客户端(包括5.1客户端)可以鉴定有短或长哈希的账户。

·         4.1之前的客户端只能鉴定有短哈希的账户。

·         对于连接的客户端,调用PASSWORD()、GRANT或SET PASSWORD的密码哈希生成操作专使用短哈希。对账户的任何更改均会生成短密码哈希值。

如前面所示,该场景的危险性在于4.1之前的客户端可能不能访问有短密码哈希值的账户。通过PASSWORD()、GRANT或SET PASSWORDA对这些账户密码的更改会产生长的密码哈希值。从该点看,4.1之前的客户端升级到4.1之前不能鉴定该账户。

要处理该问题,可以用特殊方法更改密码。例如,一般情况你可以使用SET PASSWORD按照下面的方法更改账户密码:

mysql> SET PASSWORD FOR 'some_user'@'some_host' = PASSWORD('mypass');要想更改密码但创建短哈希,使用OLD_PASSWORD()函数:

mysql> SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('mypass');当你想明显生成短哈希时,OLD_PASSWORD()很有用。

场景3:长Password列;用--old-passwords选项启动4.1或新版本的服务器:

·         短或长哈希可以保存到Password列。

·         4.1和以后版本的客户端可以鉴定有短或长哈希的账户(请注意只有不使用--old-passwords选项启动服务器,方可以创建长哈希)。

·         4.1之前的客户端只可以鉴定短哈希账户。

·         对于连接的客户端,调用PASSWORD()、GRANT或SET PASSWORD的密码哈希生成操作专使用短哈希。对账户的任何更改均会生成短密码哈希值。

在该场景中,你不能创建长密码哈希值的账户,因为--old-passwords选项防止生成长哈希。并且,如果你在使用--old-passwords选项前创建长哈希账户,当--old-passwords有时更改账户密码,结果会使账户的密码为短密码,安全性较长哈希要降低。

这些场景的不利之处可以概括为:

在场景1中,你不能利用长哈希提供更安全的鉴定。

在场景2中, 如果你没有显式使用OLD_PASSWORD()来更改密码,则4.1之前的客户端不能再访问短哈希账户。

在场景3中,--old-passwords防止短哈希账户不可访问,但密码更改操作使账户的长哈希转换为短哈希,当--old-passwords有效时不能将它改回长哈希。

5.7.9.1. 更改应用程序密码哈希值的含义
升级到MySQL4.1或更新版本后,使用PASSWORD()为自己的目的生成密码的应用程序会出现兼容性问题。应用程序实际不应这样做,因为PASSWORD()只应用来管理MySQL账户的密码。但一些应用程序使用PASSWORD()用于自己的目的。

如果你从MySQL 4.1之前的版本升级到4.1或以后版本,并在生成长密码哈希值的条件下运行服务器,应用程序使用PASSWORD()破解自己的密码。这种情况下推荐的方法是修改应用程序,使用其它函数,例如SHA1()或MD5(),来产生哈希值。如果不行,你可以使用OLD_PASSWORD()函数,该函数用来提供旧格式的短哈希。但是,请注意OLD_PASSWORD()可能有一天不再被支持。

如果服务器运行在生成短哈希的条件下,可以使用 OLD_PASSWORD()但与PASSWORD()等同。

将MySQL数据库从4.0或更低版本移植到4.1或更高版本的PHP编程人员应参阅旧客户端。

论坛徽章:
0
93 [报告]
发表于 2008-04-15 13:11 |只看该作者

5.8. MySQL用户账户管理

本节描述如何为MySQL服务器的客户端设置账户。讨论了下面的主题:

·         MySQL使用的账户名和密码的含义,以及如何比较你的操作系统所使用的账户名和密码

·         如何设置新账户并移除已有账户

·         如何更改密码

·         安全使用密码指导

·         如何使用安全SSL连接

5.8.1. MySQL用户名和密码
用用户名和客户端或主机定义MySQL账户,用户可以根据这些名称来连接服务器。账户也有密码。MySQL和操作系统使用用户名和密码的方式有几处区别:

·         MySQL用于鉴定目的用户名与Windows或Unix使用的用户名(登录名)没有关系。在Unix中,大多数MySQL客户端默认试图使用当前Unix的用户名作为MySQL用户名来登录,但这样只是为了方便。 默认值可以很容易被覆盖,因为客户端程序允许用-u或--user选项来指定用户名。因为这表示任何人可以试图使用任何用户名来连接服务器,除非所有MySQL账户有密码,否则你不能使数据库保持安全。通过为没有密码的账户指定用户名,任何人能够成功连接服务器。

·         MySQL用户名最大客达16字符长。这样可以限制MySQL服务器和客户端之间的硬编码,并且防止通过修改mysql数据库中表的定义来偷窃密码。

注:你应绝对不要以任何方式修改mysql数据库中的任何表,只能运行MySQL分发中专为此目的提供的脚本。将MySQL系统表重新定义为其它方式会导致未定义的(和不支持的!)行为。

操作系统用户名与MySQL用户名完全不相关,甚至最大长度可能不同。例如, Unix用户名限制为8个字符。

·         MySQL密码与登录到你的操作系统的密码没有关系。不需要将你用来登录Windows或Unix机器的密码和你用来访问该机器上的MySQL服务器的密码关联起来。

·         MySQL的加密密码使用自己的算法。该加密算法不同于Unix登录过程使用的算法。MySQL密码加密与PASSWORD()SQL函数的方法相同。Unix密码加密与ENCRYPT()SQL函数的方法相同。PASSWORD()和ENCRYPT()函数的描述参见12.9.2节,“加密函数”。从版本4.1 起,MySQL使用更强的鉴定方法,同以前的版本相比可以在连接过程中提供更好的密码保护。即使TCP/IP包被截取或mysql数据库被捕获也很安全。(在前面的版本中,即使密码以加密形式保存到user表中,仍可以通过加密密码值来连接MySQL服务器)。

当安装MySQL时,授权表装载时有一系列初使账户。这些账户的名称和访问权限见2.9.3节,“使初始MySQL账户安全”,其中还讨论了如何未这些账户赋予密码。因此,你一般应使用GRANT和REVOKE语句来设置、修改和移除MySQL账户。参见13.5.1.3节,“GRANT和REVOKE语法”。

当用命令行客户端连接MySQL服务器时,你应为想要使用的账户指定用户名和密码:

shell> mysql --user=monty --password=guess db_name如果你想用较短的选项,命令应为:

shell> mysql -u monty -pguess db_name-p选项和后面的密码值之间绝对不能有空格。参见5.7.4节,“与MySQL服务器连接”。

前面的命令包括命令行中的密码值,会很危险。参见5.8.6节,“使你的密码安全”。要想避免,指定--password或-p选项后面不跟任何密码值:

shell> mysql --user=monty --password db_nameshell> mysql -u monty -p db_name然后客户端程序输出提示符并等待你输入密码。(在这些示例中,db_name并不为密码,因为用空格将它同前面的密码项隔离开了)。

在一些系统中,MySQL用来提示输入密码的库调用自动将密码限制到8个字符。这是系统库的问题,而不是MySQL的问题。MySQL本身并不限制密码的长度。要解决该问题,将MySQL密码改为8个字符和更少字符的值,或将密码放入选项文件中。

5.8.2. 向MySQL增加新用户账户
可以用两种方式创建MySQL账户:

·         使用GRANT语句

·         直接操作MySQL授权表

最好的方法是使用GRANT语句,因为这样更精确,错误少。从MySQL 3.22.11起提供了GRANT;其语法见13.5.1.3节,“GRANT和REVOKE语法”。

创建账户的其它方法是使用MySQL账户管理功能的第三方程序。phpMyAdmin即是一个程序。

下面的示例说明如何使用MySQL客户端程序来设置新用户。假定按照2.9.3节,“使初始MySQL账户安全”描述的 默认值来设置权限。这说明为了更改,你必须以MySQL root用户连接MySQL服务器,并且root账户必须有mysql数据库的INSERT权限和RELOAD管理权限。

首先,使用MySQL程序以MySQL root用户来连接服务器:

shell> MySQL --user=root MySQL如果你为root账户指定了密码,还需要为该MySQL命令和本节中的其它命令提供--password或-p选项。

以root连接到服务器上后,可以添加新账户。下面的语句使用GRANT来设置四个新账户:

mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost'    ->     IDENTIFIED BY 'some_pass' WITH GRANT OPTION;mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%'    ->     IDENTIFIED BY 'some_pass' WITH GRANT OPTION;mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';mysql> GRANT USAGE ON *.* TO 'dummy'@'localhost';用GRANT语句创建的账户有下面的属性:

·         其中两个账户有相同的用户名monty和密码some_pass。两个账户均为超级用户账户,具有完全的权限可以做任何事情。一个账户 ('monty'@'localhost')只用于从本机连接时。另一个账户('monty'@'%')可用于从其它主机连接。请注意monty的两个账户必须能从任何主机以monty连接。没有localhost账户,当monty从本机连接时,mysql_install_db创建的localhost的匿名用户账户将占先。结果是,monty将被视为匿名用户。原因是匿名用户账户的Host列值比'monty'@'%'账户更具体,这样在user表排序顺序中排在前面。(user表排序的讨论参见5.7.5节,“访问控制, 阶段1:连接核实”)。

·         一个账户有用户名admin,没有密码。该账户只用于从本机连接。授予了RELOAD和PROCESS管理权限。这些权限允许admin用户执行mysqladmin reload、mysqladmin refresh和mysqladmin flush-xxx命令,以及mysqladmin processlist。未授予访问数据库的权限。你可以通过GRANT语句添加此类权限。

·         一个账户有用户名dummy,没有密码。该账户只用于从本机连接。未授予权限。通过GRANT语句中的USAGE权限,你可以创建账户而不授予任何权限。它可以将所有全局权限设为'N'。假定你将在以后将具体权限授予该账户。

除了GRANT,你可以直接用INSERT语句创建相同的账户,然后使用FLUSH PRIVILEGES告诉服务器重载授权表:

shell> mysql --user=root mysqlmysql> INSERT INTO user    ->     VALUES('localhost','monty',PASSWORD('some_pass'),    ->     'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');mysql> INSERT INTO user    ->     VALUES('%','monty',PASSWORD('some_pass'),    ->     '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;当你用INSERT创建账户时使用FLUSH PRIVILEGES的原因是告诉服务器重读授权表。否则,只有重启服务器后更改方会被注意到。使用 GRANT,则不需要使用FLUSH PRIVILEGES。

用INSERT使用PASSWORD()函数是为了加密密码。GRANT语句为你加密密码,因此不需要PASSWORD()。

'Y'值启用账户权限。对于admin账户,还可以使用更加可读的INSERT扩充的语法(使用SET)。

在为dummy账户的INSERT语句中,只有user表中的Host、User和Password列记录为指定的值。没有一个权限列为显式设置,因此MySQL将它们均指定为 默认值'N'。这样等同于GRANT USAGE的操作。

请注意要设置超级用户账户,只需要创建一个权限列设置为'Y'的user表条目。user表权限为全局权限,因此其它 授权表不再需要条目。

下面的例子创建3个账户,允许它们访问专用数据库。每个账户的用户名为custom,密码为obscure。

要想用GRANT创建账户,使用下面的语句:

shell> MySQL --user=root MySQLshell> mysql --user=root mysqlmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP    ->     ON bankaccount.*    ->     TO 'custom'@'localhost'    ->     IDENTIFIED BY 'obscure';mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP    ->     ON expenses.*    ->     TO 'custom'@'whitehouse.gov'    ->     IDENTIFIED BY 'obscure';mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP    ->     ON customer.*    ->     TO 'custom'@'server.domain'    ->     IDENTIFIED BY 'obscure';这3个账户可以用于:

·         第1个账户可以访问bankaccount数据库,但只能从本机访问。

·         第2个账户可以访问expenses数据库,但只能从主机whitehouse.gov访问。

·         第3个账户可以访问customer数据库,但只能从主机server.domain访问。

要想不用GRANT设置custom账户,使用INSERT语句直接修改 授权表:

shell> mysql --user=root mysqlmysql> INSERT INTO user (Host,User,Password)    ->     VALUES('localhost','custom',PASSWORD('obscure'));mysql> INSERT INTO user (Host,User,Password)    ->     VALUES('whitehouse.gov','custom',PASSWORD('obscure'));mysql> INSERT INTO user (Host,User,Password)    ->     VALUES('server.domain','custom',PASSWORD('obscure'));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('server.domain','customer','custom',    ->     'Y','Y','Y','Y','Y','Y');mysql> FLUSH PRIVILEGES; 前3个INSERT语句在user表中加入条目,允许用户custom从各种主机用给定的密码进行连接,但不授予全局权限(所有权限设置为 默认值'N')。后面3个INSERT语句在user表中加入条目,为custom授予bankaccount、expenses和customer数据库权限,但只能从合适的主机访问。通常若直接修改 授权表,则应告诉服务器用FLUSH PRIVILEGES重载授权表,使权限更改生效。

如果你想要让某个用户从给定域的所有机器访问(例如,mydomain.com),你可以在账户名的主机部分使用含‘%’通配符的GRANT语句:

mysql> GRANT ...    ->     ON *.*    ->     TO 'myname'@'%.mydomain.com'    ->     IDENTIFIED BY 'mypass';要想通过直接修改授权表来实现:

mysql> INSERT INTO user (Host,User,Password,...)    ->     VALUES('%.mydomain.com','myname',PASSWORD('mypass'),...);mysql> FLUSH PRIVILEGES;

论坛徽章:
0
94 [报告]
发表于 2008-04-15 13:12 |只看该作者
5.8.3. 从MySQL删除用户账户
要想移除账户,应使用DROP USER语句,请参见13.5.1.2节,“DROP USER语法”。

5.8.4. 限制账户资源
限制MySQL服务器资源使用的一个方法是将max_user_connections系统变量设置为非零值。但是,该方法严格限于全局,不允许管理具体账户。并且,它只限制使用单一账户同时连接的数量,而不是客户端连接后的操作。许多MySQL管理员对两种类型的控制均感兴趣,特别是Internet服务提供者。

在MySQL 5.1中,你可以为具体账户限制下面的服务器资源:

·         账户每小时可以发出的查询数

·         账户每小时可以发出的更新数

·         账户每小时可以连接服务器的次数

客户端可以执行的语句根据查询限制来记数。只有修改数据库或表的语句根据更新限制来记数。

还可以限制每个账户的同时连接服务器的连接数。

本文中的账户为user表中的单个记录。根据User和Host列值唯一识别每个账户。

做为使用该特性的先决条件,mysql数据库的user表必须包含资源相关的列。资源限制保存在max_questions、max_updates、max_connections和max_user_connections列内。如果user表没有这些列,必须对它进行升级;参见2.10.2节,“升级授权表”。

要想用GRANT语句设置资源限制,使WITH子句来命名每个要限制的资源和根据每小时记数的限制值。例如,要想只以限制方式创建可以访问customer数据库的新账户,执行该语句:

mysql> GRANT ALL ON customer.* TO 'francis'@'localhost'    ->     IDENTIFIED BY 'frank'    ->     WITH MAX_QUERIES_PER_HOUR 20    ->          MAX_UPDATES_PER_HOUR 10    ->          MAX_CONNECTIONS_PER_HOUR 5    ->          MAX_USER_CONNECTIONS 2;限制类型不需要全部在WITH子句中命名,但已经命名的可以按任何顺序。每个每小时限制值均应为整数,代表每小时的记数。如果GRANT语句没有WITH子句,则每个限制值设置为 默认值零(即没有限制)。对于MAX_USER_CONNECTIONS,限制为整数,表示账户一次可以同时连接的最大连接数。如果限制设置为 默认值零,则根据MAX_USER_CONNECTIONS系统变量确定该账户可以同时连接的数量。

要想设置或更改已有账户的限制,在全局级别使用GRANT USAGE语句(在*.*)。下面的语句可以将francis的查询限制更改为100:

mysql> GRANT USAGE ON *.* TO 'francis'@'localhost'    ->     WITH MAX_QUERIES_PER_HOUR 100;该语句没有改变账户的已有权限,只修改了指定的限制值。

要想取消已有限制,将该值设置为零。例如,要想取消francis每小时可以连接的次数的限制,使用该语句:

mysql> GRANT USAGE ON *.* TO 'francis'@'localhost'    ->     WITH MAX_CONNECTIONS_PER_HOUR 0;当账户使用资源时如果有非零限制,则对资源使用进行记数。

服务器运行时,它统计每个账户使用资源的次数。如果账户在最后一个小时的连接次数达到限制,该账户的进一步的连接被拒绝。类似地,如果账户达到查询或更新次数的限制,进一步的查询或更新被拒绝。在这种情况下,会给出相关错误消息。

根据每个账户进行资源计算,而不是根据每个客户端。例如,如果你的账户的查询限制为50,你不能通过两个客户端同时连接服务器将限制增加到100。两个连接的查询被计算到一起。

可以为所有账户从全局重设当前的每小时资源使用记数,或单独重设给定的账户:

·         要想将所有账户当前的记数重设为零,可以执行FLUSH USER_RESOURCES语句。还可以通过重载授权表来重设记数(例如,使用FLUSH PRIVILEGES语句或mysqladmin reload命令)。

·         将具体账户的限制重新授予任何值,可以将它设置为零。要想实现,按照前面所述使用GRANT USAGE,并将限制值指定为该账户当前的限制值。

计数器重设不影响MAX_USER_CONNECTIONS限制。

当服务器启动时所有记数从零开始。

5.8.5. 设置账户密码
可以用mysqladmin命令在命令行指定密码:
shell> mysqladmin -u user_name -h host_name password "newpwd"该命令重设密码的账户为user表内匹配User列的user_name和Host列你发起连接的客户端的记录。

为账户赋予密码的另一种方法是执行SET PASSWORD语句:

mysql> SET PASSWORD FOR 'jeffrey'@'%' = PASSWORD('biscuit');只有root等可以更新mysql数据库的用户可以更改其它用户的密码。如果你没有以匿名用户连接,省略FOR子句便可以更改自己的密码:

mysql> SET PASSWORD = PASSWORD('biscuit');你还可以在全局级别使用GRANT USAGE语句(在*.*)来指定某个账户的密码而不影响账户当前的权限:

mysql> GRANT USAGE ON *.* TO 'jeffrey'@'%' IDENTIFIED BY 'biscuit';一般情况下最好使用上述方法来指定密码,你还可以直接修改user表:

·         要想在创建新账户时建立密码,在Password列提供一个值:

·                shell> mysql -u root mysql·                mysql> INSERT INTO user (Host,User,Password)·                     -> VALUES('%','jeffrey',PASSWORD('biscuit'));·                mysql> FLUSH PRIVILEGES;·                 ·         要想更改已有账户的密码,使用UPDATE来设置Password列值:

·                shell> mysql -u root mysql·                 mysql> UPDATE user SET Password = PASSWORD('bagel')·                       -> WHERE Host = '%' AND User = 'francis';·                mysql> FLUSH PRIVILEGES;当你使用SET PASSWORD、INSERT或UPDATE指定账户的密码时,必须用PASSWORD()函数对它进行加密。(唯一的特例是如果密码为空,你不需要使用PASSWORD())。需要使用PASSWORD()是因为user表以加密方式保存密码,而不是明文。如果你忘记了,你可能会象这样设置密码:

shell> mysql -u root mysqlmysql> INSERT INTO user (Host,User,Password)    -> VALUES('%','jeffrey','biscuit');mysql> FLUSH PRIVILEGES; 结果是密码'biscuit'保存到user表后没有加密。当jeffrey使用该密码连接服务器时,值被加密并同保存在user表中的进行比较。但是,保存的值为字符串'biscuit',因此比较将失败,服务器拒绝连接:

shell> mysql -u jeffrey -pbiscuit testAccess denied如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置密码,它们均会加密密码。在这种情况下,不需要使用 PASSWORD()函数。

注释:PASSWORD()加密不同于Unix密码加密。参见5.8.1节,“MySQL用户名和密码”。

论坛徽章:
0
95 [报告]
发表于 2008-04-15 13:12 |只看该作者
5.8.6. 使你的密码安全
在管理级别,你决不能将mysql.user表的访问权限授予任何非管理账户。

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

·         使用一个在命令行上-pyour_pass或--password=your_pass的选项。例如:

·                shell> mysql -u francis -pfrank db_name这很方便但是不安全,因为你的密码对系统状态程序(例如ps)变得可见,它可以被其他的用户调用来显示命令行。一般MySQL客户在他们的初始化顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可见的。

·         使用一个-p或--password选项(没有指定密码)。在这种情况下,客户端程序请求来自终端的密码:

·                shell> mysql -u francis -p db_name·                Enter password: ******** “*”字符指示输入密码的地方。输入密码时密码看不见。

因为它对其他用户不可见,与在命令行上指定它相比,这样进入你的密码更安全。然而,这个输入一个密码的方法仅仅为你交互式运行程序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户端,就没有从终端输入入密码的机会。在某些系统中,你甚至会发现脚本的第一行被(错误地)读并解释为你的密码!

·         在一个配置文件中存储你的密码。例如,在Unix中,你可在主目录的“.my.cnf”文件中的[client]节列出你的密码:

·                [client]·                password=your_pass如果你在“.my.cnf”里面存储密码,除了你本人其它人不能访问该文件。保证文件的访问模式是400或600。例如:

shell> chmod 600 .my.cnf关于选项文件的详细讨论参见4.3.2节,“使用选项文件”。

·         你可在MYSQL_PWD环境变量中存储密码。但是这种指定MySQL密码的方法是极不安全的,不应该使用。ps的某些版本包括显示运行进程的环境的选项;如果你设定MYSQL_PWD,你的密码将被运行ps的所有人看见,甚至在没有这样一个版本的ps的系统上,没有其它方法观察到进程环境的假设是不明智的。参见附录F:环境变量。

总之,最安全的方法是让客户端程序提示输入密码或在适当保护的选项文件中指定密码。

5.8.7. 使用安全连接
5.8.7.1. SSL基本概念
5.8.7.2. 需求(OpenSSL)
5.8.7.3. 使用yaSSL
5.8.7.4. 为MySQL设置SSL证书
5.8.7.5. SSL GRANT 选项
5.8.7.6. SSL命令行选项
5.8.7.7. 用SSH以远程方式从Windows连接到MySQL
MySQL支持MySQL客户端和服务器之间的安全(加密的)连接所使用的安全套接字层(SSL)协议。本节讨论如何使用SSL连接。还描述了在Windows中设置SSH的方法。
MySQL的标准配置倾向于尽可能快,因此默认情况不使用加密连接。使用该协议会使客户端/服务器协议慢得多。对数据进行加密非常耗CPU,需要计算机多做许多工作,会延迟MySQL的其它任务。对于需要通过加密连接提供安全的应用程序,可以保证额外的计算。

MySQL允许在连接前启用加密。你可以根据具体应用程序的需求选择普通未加密连接或安全加密SSL连接。

5.8.7.1. SSL基本概念
要想理解MySQL如何使用SSL,需要解释一些基本SSL和X509概念。熟悉的人们可以跳过该部分。
默认情况下,MySQL在客户端和服务器之间使用未加密的连接。这说明可以访问网络的部分人可以看到你的通信,并看到发送和接收的数据。他们甚至可以更改在客户端和服务器之间传递的数据。要想提高安全性,当调用客户端程序时,你可以通过--compress选项压缩客户端/服务器之间的通信。但是,这样并不能阻挡住顽固的攻击者。

当你需要以安全方式在网络中传递信息时,未加密的连接是不可接受的。加密是使任何数据不可读的方法。事实上,今天的许多惯例需要加密算法提供更加安全的要素。它们应能抵抗各种已知的攻击,例如更改加密消息的顺序或两次重放数据。

SSL是一种使用不同的加密算法确保从公用网接收到的数据是可信的协议。它具有检测数据更改、丢失或重放的机制。SSL还包括使用 X509标准提供身份认证的算法。

使用X509,可以识别Internet上的某些人。通常用于电子商务应用程序中。按照基本概念,应有某种称之为“认证机构”(或CA)的机构,可以向请求者分发电子证书。证书依赖非对称加密算法,有两个加密密钥(公共密钥和私人密钥)。认证持有者可以向其它方出示证书来证明身份。证书包括持有者的公共密钥。只能使用对应的私人密钥对含该公共密钥的加密数据进行解密,私人密钥由证书持有者拥有。

如果你需要关于SSL、X509、或加密的详细信息,使用Internet搜索引擎来搜索你感兴趣的关键字。

5.8.7.2. 需求(OpenSSL)
要想在MySQL服务器和客户端程序之间使用SSL连接,系统必须能够支持OpenSSL。如果用支持内嵌式yaSSL的MySQL版本,不要读该节,但应阅读5.8.7.3节,“使用yaSSL”。

要想获得安全的MySQL连接,必须:

1.    安装OpenSSL库。我们已经测试了带OpenSSL 0.9.6的MySQL。如果你需要OpenSSL,请访问http://www.openssl.org

2.    配置MySQL,用--with-vio和--with-openssl选项运行configure脚本。

3.    确保升级了授权表,使mysql.user表内包含SSL相关列。如果 授权表是从MySQL 4.0.0之前的版本升级,这很重要。升级过程见2.10.2节,“升级授权表”。

4.    要想检查是否运行的mysqld服务器支持OpenSSL,应检查have_openssl系统变量的值:

5.            mysql> SHOW VARIABLES LIKE 'have_openssl';6.            +---------------+-------+7.            | Variable_name | Value |8.            +---------------+-------+9.            | have_openssl  | YES   |10.        +---------------+-------+如果值为YES,服务器支持OpenSSL连接。

5.8.7.3. 使用yaSSL
使用MySQL的内嵌式yaSSL支持,可以很容易地使用安全连接。不需要安装OpenSSL和执行5.8.7.2节,“需求(OpenSSL)”中的步骤。并且,MySQL和yaSSL使用相同的许可模型。

当前,在以下平台上支持yaSSL:

·         Linux/x86-64 Red Hat Enterprise 3.0

·         Linux RHAS21 Itanium-2,带gcc,静态链接

·         Linux Itanium-2,带gcc

·         Windows

当从源码构建MySQL时如果你想要启用yaSSL,应这样配置MySQL:

./configure --with-yassl=yes要想启动MySQL服务器支持yaSSL,使用支持OpenSSL的相同的选项,并识别建立安全连接需要的证书:

shell> mysqld --ssl-ca=cacert.pem \       --ssl-cert=server-cert.pem \       --ssl-key=server-key.pem·         --ssl-ca识别认证机构证书。

·         --ssl-cert识别服务器证书。

·         --ssl-key识别客户证书。

要想用yaSSL支持建立与MySQL服务器的安全连接,应这样启动客户端:

shell> mysql --ssl-ca=cacert.pem \       --ssl-cert=server-cert.pem \       --ssl-key=server-key.pem换句话说,选项与服务器的相同,并且认证机构证书必须相同。

要想从应用程序建立安全连接,调用mysql_real_connect()之前,应使用mysql_ssl_set()API函数来设置相应认证选项。参见25.2.3.64节,“mysql_ssl_set()”。

5.8.7.4. 为MySQL设置SSL证书
下面是一个为MySQ设置SSL证书的例子:
DIR=`pwd`/opensslPRIV=$DIR/private mkdir $DIR $PRIV $DIR/newcertscp /usr/share/ssl/openssl.cnf $DIRreplace ./demoCA $DIR -- $DIR/openssl.cnf # Create necessary files: $database, $serial and $new_certs_dir# directory (optional) touch $DIR/index.txtecho "01" > $DIR/serial ## Generation of Certificate Authority(CA)# openssl req -new -x509 -keyout $PRIV/cakey.pem -out $DIR/cacert.pem \    -config $DIR/openssl.cnf # Sample output:# Using configuration from /home/monty/openssl/openssl.cnf# Generating a 1024 bit RSA private key# ................++++++# .........++++++# writing new private key to '/home/monty/openssl/private/cakey.pem'# Enter PEM pass phrase:# Verifying password - Enter PEM pass phrase:# -----# You are about to be asked to enter information that will be# incorporated into your certificate request.# What you are about to enter is what is called a Distinguished Name# or a DN.# There are quite a few fields but you can leave some blank# For some fields there will be a default value,# If you enter '.', the field will be left blank.# -----# Country Name (2 letter code) [AU]:FI# State or Province Name (full name) [Some-State]:.# Locality Name (eg, city) []:# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB# Organizational Unit Name (eg, section) []:# Common Name (eg, YOUR name) []:MySQL admin# Email Address []: ## Create server request and key#openssl req -new -keyout $DIR/server-key.pem -out \    $DIR/server-req.pem -days 3600 -config $DIR/openssl.cnf # Sample output:# Using configuration from /home/monty/openssl/openssl.cnf# Generating a 1024 bit RSA private key# ..++++++# ..........++++++# writing new private key to '/home/monty/openssl/server-key.pem'# Enter PEM pass phrase:# Verifying password - Enter PEM pass phrase:# -----# You are about to be asked to enter information that will be# incorporated into your certificate request.# What you are about to enter is what is called a Distinguished Name# or a DN.# There are quite a few fields but you can leave some blank# For some fields there will be a default value,# If you enter '.', the field will be left blank.# -----# Country Name (2 letter code) [AU]:FI# State or Province Name (full name) [Some-State]:.# Locality Name (eg, city) []:# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB# Organizational Unit Name (eg, section) []:# Common Name (eg, YOUR name) []:MySQL server# Email Address []:## Please enter the following 'extra' attributes# to be sent with your certificate request# A challenge password []:# An optional company name []: ## Remove the passphrase from the key (optional)# openssl rsa -in $DIR/server-key.pem -out $DIR/server-key.pem ## Sign server cert#openssl ca  -policy policy_anything -out $DIR/server-cert.pem \    -config $DIR/openssl.cnf -infiles $DIR/server-req.pem # Sample output:# Using configuration from /home/monty/openssl/openssl.cnf# Enter PEM pass phrase:# Check that the request matches the signature# Signature ok# The Subjects Distinguished Name is as follows# countryName           RINTABLE:'FI'# organizationName      RINTABLE:'MySQL AB'# commonName            RINTABLE:'MySQL admin'# Certificate is to be certified until Sep 13 14:22:46 2003 GMT# (365 days)# Sign the certificate? [y/n]:y### 1 out of 1 certificate requests certified, commit? [y/n]y# Write out database with 1 new entries# Data Base Updated ## Create client request and key#openssl req -new -keyout $DIR/client-key.pem -out \    $DIR/client-req.pem -days 3600 -config $DIR/openssl.cnf # Sample output:# Using configuration from /home/monty/openssl/openssl.cnf# Generating a 1024 bit RSA private key# .....................................++++++# .............................................++++++# writing new private key to '/home/monty/openssl/client-key.pem'# Enter PEM pass phrase:# Verifying password - Enter PEM pass phrase:# -----# You are about to be asked to enter information that will be# incorporated into your certificate request.# What you are about to enter is what is called a Distinguished Name# or a DN.# There are quite a few fields but you can leave some blank# For some fields there will be a default value,# If you enter '.', the field will be left blank.# -----# Country Name (2 letter code) [AU]:FI# State or Province Name (full name) [Some-State]:.# Locality Name (eg, city) []:# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB# Organizational Unit Name (eg, section) []:# Common Name (eg, YOUR name) []:MySQL user# Email Address []:## Please enter the following 'extra' attributes# to be sent with your certificate request# A challenge password []:# An optional company name []: ## Remove a passphrase from the key (optional)#openssl rsa -in $DIR/client-key.pem -out $DIR/client-key.pem ## Sign client cert# openssl ca  -policy policy_anything -out $DIR/client-cert.pem \    -config $DIR/openssl.cnf -infiles $DIR/client-req.pem # Sample output:# Using configuration from /home/monty/openssl/openssl.cnf# Enter PEM pass phrase:# Check that the request matches the signature# Signature ok# The Subjects Distinguished Name is as follows# countryName           RINTABLE:'FI'# organizationName      RINTABLE:'MySQL AB'# commonName            RINTABLE:'MySQL user'# Certificate is to be certified until Sep 13 16:45:17 2003 GMT# (365 days)# Sign the certificate? [y/n]:y### 1 out of 1 certificate requests certified, commit? [y/n]y# Write out database with 1 new entries# Data Base Updated ## Create a my.cnf file that you can use to test the certificates# cnf=""cnf="$cnf [client]"cnf="$cnf ssl-ca=$DIR/cacert.pem"cnf="$cnf ssl-cert=$DIR/client-cert.pem"cnf="$cnf ssl-key=$DIR/client-key.pem"cnf="$cnf [mysqld]"cnf="$cnf ssl-ca=$DIR/cacert.pem"cnf="$cnf ssl-cert=$DIR/server-cert.pem"cnf="$cnf ssl-key=$DIR/server-key.pem"echo $cnf | replace " " '' > $DIR/my.cnf

要想测试SSL连接,按下面方法启动服务器,其中$DIR是示例my.cnf选项文件安装的路径名:

shell> MySQLd --defaults-file=$DIR/my.cnf &然后使用相同的选项文件调用客户端程序:

shell> MySQL --defaults-file=$DIR/my.cnf如果你有MySQL源码分发版,还可以修改前面的my.cnf文件来指向SSL目录中的示范证书和密钥文件来测试你的设置。

论坛徽章:
0
96 [报告]
发表于 2008-04-15 13:13 |只看该作者
5.8.7.5. SSL GRANT 选项
MySQL可以检查X509证书的属性和基于用户名和密码的通用鉴定方法。要想为MySQL账户指定SSL相关选项,使用GRANT语句的REQUIRE子句。参见13.5.1.3节,“GRANT和REVOKE语法”。

有多种可能来限制一个账户的连接类型:

·         如果账户没有SSL或X509需求,如果用户名和密码合法,允许未加密的连接。但是,如果客户有正确的证书和密钥文件,在客户选项中可以使用加密连接。

·         REQUIRE SSL选项限制服务器只允许该账户的SSL加密连接。请注意如果有ACL记录允许非SSL连接,该选项会被忽略。

·                  mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'·                     -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;·         REQUIRE X509表示客户必须有合法证书但确切的证书、分发者和主体不重要。唯一的需求是应可以被某个CA认证机构验证它的签名。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'·                    -> IDENTIFIED BY 'goodsecret' REQUIRE X509;·         REQUIRE ISSUER 'issuer'限制连接企图,即客户必须出示CA 'issuer'签发的合法X509证书。如果客户出示了一个合法证书,但是是由不同的分发者签发,服务器拒绝连接。使用X509证书表示要加密,因此不需要SSL选项。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'·                    -> IDENTIFIED BY 'goodsecret'·                    -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/·                       O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';请注意ISSUER值应做为单一字符串输入。

·         REQUIRE SUBJECT 'subject' 限制连接企图,即客户必须出示主题为'subject'的合法X509证书。如果客户出示了一个合法证书,但是有不同的主题,服务器拒绝连接。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'·                    -> IDENTIFIED BY 'goodsecret'·                    -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/·                       O=MySQL demo client certificate/       CN=Tonu Samuel/Email=tonu@example.com';请注意SUBJECT值应做为单一字符串输入。

·         REQUIRE CIPHER 'cipher'用来确保使用足够强的密码和密钥长度。如果使用旧的短加密密钥算法,SSL本身可能很弱。使用该选项,我们可以索取确切的加密方法来连接。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'·                    -> IDENTIFIED BY 'goodsecret'    -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';在REQUIRE子句中,可以结合使用SUBJECT、ISSUER和CIPHER选项:

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'    -> IDENTIFIED BY 'goodsecret'    -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/       O=MySQL demo client certificate/       CN=Tonu Samuel/Email=tonu@example.com'    -> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/       O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'    -> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';请注意SUBJECT和ISSUER值应做为单一字符串输入。

在MySQL 5.1中,在REQUIRE选项之间可以选用AND关键字。

选项的顺序不重要,但任何选项不能用两次。

5.8.7.6. SSL命令行选项
下面列出了规定SSL、证书文件和密钥文件使用的选项。它们可以位于命令行中或选项文件中。
·         --ssl

对于服务器,该选项规定该服务器允许SSL连接。对于客户端程序,它允许客户使用SSL连接服务器。单单该选项不足以使用SSL连接。还必须指定--ssl-ca、--ssl-cert和--ssl-key选项。

通常从反向使用该选项表示不应使用SSL。要想实现,将选项指定为--skip-ssl或--ssl=0。

请注意使用--ssl不需要SSL连接。例如,如果编译的服务器或客户不支持SSL,则使用普通的未加密的连接。

确保使用SSL连接的安全方式是使用含REQUIRE SSL子句的GRANT语句在服务器上创建一个账户。然后使用该账户来连接服务器,服务器和客户端均应启用SSL支持。

·         --ssl-ca=file_name

含可信SSL CA的清单的文件的路径。

·         --ssl-capath=directory_name

包含pem格式的可信SSL CA证书的目录的路径。

·         --ssl-cert=file_name

SSL证书文件名,用于建立安全连接。

·         --ssl-cipher=cipher_list

允许的用于SSL加密的密码的清单。cipher_list的格式与OpenSSL ciphers命令相同。

示例:--ssl-cipher=ALL:-AES:-EXP

·         --ssl-key=file_name

SSL密钥文件名,用于建立安全连接。

5.8.7.7. 用SSH以远程方式从Windows连接到MySQL
本节说明如何用SSH安全连接到远程MySQL服务器(David Carlson <dcarlson@mplcomm。com>):
1.    在Windows主机上安装SSH客户端。作为用户,我所发现的最好的非免费客户端来自http://www.vandyke.com/的SecureCRT。另一个选则是http://www.f-secure.com/的f-secure。你还可以从http://directory.google.com/Top/ ... SH/Clients/Windows/ 的Google找到一些免费客户端。

2.    启动Windows SSH客户端。设置Host_Name = yourmysqlserver_URL_or_IP。设置userid=your_userid以便登录服务器。此userid值可以与你的MySQL账户的用户名不相同。

3.    设置端口映射。可以进行远程映射(设置local_port: 3306, remote_host: yourmysqlservername_or_ip, remote_port: 3306)或本地映射(设置port: 3306, host: localhost, remote port: 3306)。

4.    进行保存,否则下次需要重设。

5.    刚创建的SSH会话登录服务器。

6.    在Windows机器上启动相应ODBC应用程序(例如Access)。

7.    在Windows中创建一个新的文件按照常用方法通过ODBC驱动程序链接MySQL,不同的是要为MySQL服务器输入localhost,而不是yourmysqlservername。

你应有使用SSH加密的ODBC连接到MySQL。

论坛徽章:
0
97 [报告]
发表于 2008-04-15 13:59 |只看该作者
5.1的手册官方是有的,你发这个有什么意义?

论坛徽章:
1
摩羯座
日期:2015-01-08 14:01:55
98 [报告]
发表于 2008-04-15 14:39 |只看该作者
原帖由 yueliangdao0608 于 2008-4-15 13:59 发表
5.1的手册官方是有的,你发这个有什么意义?



同问楼主,楼主这样贴很辛苦啊,而且没有超级链接……
SUN赞助的unix-center也有MySQL的官方教程啊……

论坛徽章:
0
99 [报告]
发表于 2008-04-15 15:19 |只看该作者
好东东,若能打包下载就更好!

论坛徽章:
0
100 [报告]
发表于 2008-04-15 15:29 |只看该作者

5.9. 备份与恢复

本节讨论如何进行数据库备份(完全备份和增量备份),以及如何执行表的维护。本节描述的SQL语句语法参见第5章:数据库管理。此处提供的大多数信息主要适合MyISAM表。InnoDB备份程序参见15.2.8节,“InnoDB数据库的备份和恢复”。

5.9.1. 数据库备份
因为MySQL表保存为文件方式,很容易备份。要想保持备份的一致性,对相关表执行LOCK TABLES操作,然后对表执行FLUSH TABLES。参见13.4.5节,“LOCK TABLES和UNLOCK TABLES语法”和13.5.5.2节,“FLUSH语法”。你只需要读锁定;这样当你复制数据库目录中的文件时,允许其它客户继续查询表。需要FLUSH TABLES语句来确保开始备份前将所有激活的索引页写入硬盘。

如果你想要进行SQL级别的表备份,你可以使用SELECT INTO ...OUTFILE或BACKUP TABLE。对于SELECT INTO ...OUTFILE, 输出的文件不能先存在。对于BACKUP TABLE也如此,因为覆盖完整的文件会有安全风险。参见13.2.7节,“SELECT语法”和13.5.2.2节,“BACKUP TABLE语法”。

备份数据库的另一个技术是使用mysqldump程序或mysqlhotcopy脚本。参见8.8节,“mysqldump:数据库备份程序”和8.9节,“mysqlhotcopy:数据库备份程序”。

1.    完全备份数据库:

2.            shell> mysqldump --tab=/path/to/some/dir --opt db_name或:

shell> mysqlhotcopy db_name /path/to/some/dir只要服务器不再进行更新,还可以只复制所有表文件(*.frm、*.MYD和*.MYI文件)。mysqlhotcopy脚本使用该方法。(但请注意如果数据库包含InnoDB表,这些方法不工作。InnoDB不将表的内容保存到数据库目录中,mysqlhotcopy只适合MyISAM表)。

3.    如果mysqld在运行则停止,然后用--log-bin[=file_name]选项来启动。参见5.11.3节,“二进制日志”。二进制日志文件中提供了  执行mysqldump之后对数据库的更改进行复制所需要的信息。

对于InnoDB表,可以进行在线备份,不需要对表进行锁定;参见8.8节,“mysqldump:数据库备份程序”。

MySQL支持增量备份:需要用--log-bin选项来启动服务器以便启用二进制日志;参见5.11.3节,“二进制日志”。当想要进行增量备份时(包含上一次完全备份或增量备份之后的所有更改),应使用FLUSH LOGS回滚二进制日志。然后,你需要将从最后的完全或增量备份的某个时刻到最后某个点的所有二进制日志复制到备份位置。这些二进制日志为增量备份;恢复时,按照下面的解释应用。下次进行完全备份时,还应使用FLUSH LOGS或mysqlhotcopy --flushlogs回滚二进制日志。参见8.8节,“mysqldump:数据库备份程序”和8.9节,“mysqlhotcopy:数据库备份程序”。

如果MySQL服务器为从复制服务器,则无论选择什么备份方法,当备份从机数据时,还应备份master.info和relay-log.info文件。恢复了从机数据后,需要这些文件来继续复制。如果从机执行复制LOAD DATA INFILE命令,你应还备份用--slave-load-tmpdir选项指定的目录中的SQL_LOAD-*文件。(如果未指定,该位置默认为tmpdir变量值)。从机需要这些文件来继续复制中断的LOAD DATA INFILE操作。

如果必须恢复MyISAM表,先使用REPAIR TABLE或myisamchk -r来恢复。99.9%的情况下该方法可以工作。如果myisamchk失败,试试下面的方法。请注意只有用--log-bin选项启动了MySQL从而启用二进制日志它才工作;参见5.11.3节,“二进制日志”。

1.    恢复原mysqldump备份,或二进制备份。

2.    执行下面的命令重新更新二进制日志:

3.            shell> mysqlbinlog hostname-bin.[0-9]* | mysql在某些情况下,你可能只想要从某个位置重新运行某些二进制日志。(通常你想要从恢复备份的日期重新运行所有二进制日志,查询不正确时例外)。关于mysqlbinlog工具和如何使用它的详细信息参见8.6节,“mysqlbinlog:用于处理二进制日志文件的实用工具”。

还可以对具体文件进行选择备份:

·         要想复制表,使用SELECT * INTO OUTFILE 'file_name' FROM tbl_name。

·         要想重载表,使用LOAD DATA INFILE 'file_name' REPLACE ...并恢复。要避免复制记录,表必须有PRIMARY KEY或一个UNIQUE索引。当新记录复制唯一键值的旧记录时,REPLACE关键字可以将旧记录替换为新记录。

如果备份时遇到服务器性能问题,可以有帮助的一个策略是在从服务器而不是主服务器上建立复制并执行备份。参见6.1节,“复制介绍”。

如果使用Veritas文件系统,可以这样备份:

1.    从客户端程序执行FLUSH TABLES WITH READ LOCK。

2.    从另一个shell执行mount vxfs snapshot。

3.    从第一个客户端执行UNLOCK TABLES。

4.    从快照复制文件。

5.    卸载快照。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP