MySQL访问控制 在这个教程的早些时候,我们曾经提到一个叫做mysql的数据库,在每一个MySQL服务中都包含这个数据库,它是用来保存用户的相关信息、他们的口令以及他们的权限的。但是,在此之前,我们一直使用root用户登录到MySQL服务,这个用户可以访问所有的数据库和数据表。 如果你的MySQL服务仅仅被通过PHP访问,而用你对于将root用户的口令告诉什么人很小心,那么root帐号可能已经足够了。但是,如果一个MySQL服务是被许多人共享的,(例如,一个Web主机希望对它的每一个用户提供同一个MySQL服务),为不同的用户设置相应的访问权限就显得很重要了。 在MySQL参考手册的第六章中详细介绍了MySQL的访问控制系统。从原理上来说,用户的访问是由mysql数据库中的五个数据表来管理的:user、db、host、tables_priv和columns_priv。如果你想直接使用INSERT、UPDATE和DELETE语句来编辑这些表,我建议你先阅读一下MySQL指南中的相关章节。而从3.22.11版本开始,MySQL提供了简单的方法来管理用户的访问。使用MySQL提供的非标准的命令GRANT和REVOKE,你可以建立用户并赋予其相应的权限,而不必关心它在前面提到的五个表中的存储形式。 使用GRANT GRANT命令用来建立新用户,指定用户口令并增加用户权限。其格式如下: mysql> GRANT ON -> TO [IDENTIFIED BY ""] -> [WITH GRANT OPTION];
|
正如你看到的,在这个命令中有许多待填的内容。让我们逐一地对它们进行介绍,并最终给出一些例子以让你对它们的协同工作有一个了解。 是一个用逗号分隔的你想要赋予的权限的列表。你可以指定的权限可以分为三种类型: 数据库/数据表/数据列权限: ALTER: 修改已存在的数据表(例如增加/删除列)和索引。 CREATE: 建立新的数据库或数据表。 DELETE: 删除表的记录。 DROP: 删除数据表或数据库。 INDEX: 建立或删除索引。 INSERT: 增加表的记录。 SELECT: 显示/搜索表的记录。 UPDATE: 修改表中已存在的记录。 全局管理权限: FILE: 在MySQL服务器上读写文件。 PROCESS: 显示或杀死属于其它用户的服务线程。 RELOAD: 重载访问控制表,刷新日志等。 SHUTDOWN: 关闭MySQL服务。 特别的权限: ALL: 允许做任何事(和root一样)。 USAGE: 只允许登录--其它什么也不允许做。 这些权限所涉及到的MySQL的特征,其中的一些我们至今还没看到,而其中的绝大部分是你所熟悉的。 定义了这些权限所作用的区域。*.*意味着权限对所有数据库和数据表有效。dbName.*意味着对名为dbName的数据库中的所有数据表有效。dbName.tblName意味着仅对名为dbName中的名为tblName的数据表有效。你甚至还可以通过在赋予的权限后面使用圆括号中的数据列的列表以指定权限仅对这些列有效(在后面我们将看到这样的例子)。 指定可以应用这些权限的用户。在MySQL中,一个用户通过它登录的用户名和用户使用的计算机的主机名/IP地址来指定。这两个值都可以使用%通配符(例如kevin@%将允许使用用户名kevin从任何机器上登录以享有你指定的权限)。 指定了用户连接MySQL服务所用的口令。它被用方括号括起,说明IDENTIFIED BY ""在GRANT命令中是可选项。这里指定的口令会取代用户原来的密码。如果没有为一个新用户指定口令,当他进行连接时就不需要口令。 这个命令中可选的WITH GRANT OPTION部分指定了用户可以使用GRANT/REVOKE命令将他拥有的权限赋予其他用户。请小心使用这项功能--虽然这个问题可能不是那么明显!例如,两个都拥有这个功能的用户可能会相互共享他们的权限,这也许不是你当初想看到的。 让我们来看两个例子。建立一个名为dbmanager的用户,他可以使用口令managedb从server.host.net连接MySQL,并仅仅可以访问名为db的数据库的全部内容(并可以将此权限赋予其他用户),这可以使用下面的GRANT命令: mysql> GRANT ALL ON db.* -> TO dbmanager@server.host.net -> IDENTIFIED BY "managedb" -> WITH GRANT OPTION;
|
现在改变这个用户的口令为funkychicken,命令格式如下: mysql> GRANT USAGE ON *.* -> TO dbmanager@server.host.net -> IDENTIFIED BY "funkychicken"; 请注意我们没有赋予任何另外的权限(the USAGE权限只能允许用户登录),但是用户已经存在的权限不会被改变。 现在让我们建立一个新的名为jessica的用户,他可以从host.net域的任意机器连接到MySQL。他可以更新数据库中用户的姓名和email地址,但是不需要查阅其它数据库的信息。也就是说他对db数据库具有只读的权限(例如,SELECT),但是他可以对Users表的name列和email列执行UPDATE操作。命令如下: mysql> GRANT SELECT ON db.* -> TO jessica@%.host.net -> IDENTIFIED BY "jessrules"; mysql> GRANT UPDATE (name,email) ON db.Users -> TO jessica@%.host.net;
|
请注意在第一个命令中我们在指定Jessica可以用来连接的主机名时使用了%(通配符)符号。此外,我们也没有给他向其他用户传递他的权限的能力,因为我们在命令的最后没有带上WITH GRANT OPTION。第二个命令示范了如何通过在赋予的权限后面的圆括号中用逗号分隔的列的列表对特定的数据列赋予权限。 使用REVOKE 正如你所预期的那样,REVOKE命令是用来去除一个用户以前被赋予的权限的。命令的语法如下: mysql> REVOKE [()] -> ON FROM ;
|
这个命令中各部分的功能和在上面的GRANT命令中时一样。要去除Jessica的合作者的DROP权限(例如,如果他经常错误地删除数据库和表),你可以使用下面的命令: mysql> REVOKE DROP ON *.* FROM idiot@%.host.net; |
去除一个用户的登录权限大概是唯一不能使用REVOKE的。REVOKE ALL ON *.*会去除用户的所有权限,但是他还可以登录,要完全地删除一个用户,你需要在user表中删除相应的记录: mysql> DELETE FROM user -> WHERE User="idiot" AND Host="%.host.net";
|
访问控制技巧 由于MySQL中访问控制系统工作的方法的影响,在建立你的用户之前你必须知道两个特征。 当建立的用户只能从MySQL服务运行的计算机上登录到MySQL服务(也就是说,你需要他们telnet到服务器并在那里运行MySQL的客户端程序,或者是使用象PHP这样的服务器端脚本语言进行通信),你大概会问自己GRANT命令的部分应该填什么内容。如果服务是运行在www.host.net。你是应该将用户设置为username@www.host.net还是username@localhost呢? 答案是,你不能依赖其中的任何一种来处理任何连接。从理论上来说,如果用户在连接时(无论是使用mysql客户端还是使用PHP的mysql_connect函数)指定了主机名,这个主机名必须与访问控制系统中的记录匹配。但是因为你也许不想强迫你的用户指定主机名(事实上,mysql客户端的用户也许根本不会指定主机名),你最好使用下面这种工作环境。 对于用户需要能够从MySQL服务在其上运行的机器上连接MySQL的情况,在MySQL访问控制系统中建立两个用户记录:一个使用实际的主机名(例如,username@www.host.net),另一个使用localhost(例如,username@localhost),当然,你需要为两个用户分别grant/revoke所有的权限。 MySQL管理者所要面对的另一个带有普通性的问题是一个其中的主机名使用了通配符的用户记录(例如,前面提到jessica@%.host.net)没起作用。发生这种情况,一般是由于MySQL访问控制系统中记录的优先级的问题。具体地说,越具体的主机名优先级越高(例如,www.host.net是最具体的,%.host.net是比较具体的,而%是最不具体的)。 在一个新安装后,MySQL访问控制系统包含两个匿名用户记录(它允许在当前主机上使用任何用户名进行连接--这两个记录分别支持从localhost连接以及从服务器的实现的主机名进行连接),以及两个root用户目录。我们上面讨论的情况发生时是由于匿名用户目录的优先级比我们的新记录高,因为他们的主机名更具体。 让我们看看www.host.net上user表的内容,我们假定已经添加了Jessica的记录。数据行是按照MySQL服务在确认连接时的优先级排列的: 正如你看到的,因为Jessica的记录的主机名最不具体,它的优先级最低。当Jessica试图从www.host.net连接时,MySQL服务将他的连接匹配为一个匿名用户记录(空白的User值与任何人匹配)。因为这些匿名记录不需要口令,而也许Jessica输入了他的口令,MySQL将拒绝这个连接。即使Jessica没有输入口令,他可能也只被给予了匿名用户的权限(非常有限),而不是他原来被赋予的权限。 解决这个问题的方法是,要么你删除匿名用户的记录(DELETE FROM user WHERE User=""),要么再为所有的可能从localhost连接的用户指定两条记录(例如,相对于localhost以及相对于服务器的实际主机名): 因为要为每个用户维护三个用户记录(以及相应的三套权限)会很麻烦,所以我们推荐你删除匿名用户,除非你需要用他们来完成什么特殊的应用:
 
2/2 首页 上一页 1 2 |