口令值可以是空或非空,不允许用通配符。一个空口令不意味着匹配任何口令,用户必须不指定口令。
口令以一个加密过的值存储,不是一个字面上的文本。如果你在Password列中存储一个照字面上的口令,用户将不能连接!GRANT语句和mysqladmin password命令为你自动加密口令,但是如果你用诸如INSERT、REPLACE、UPDATE或SETPASSWORD等命令,一定要用PASSWORD("new_password")而不是简单的"new_password"来指定口令。
Db 在columns_priv和tables_priv表中,Db值必须是真正的数据库名(照字面上),不允许模式和空白。在db和host中,Db值可以以字面意义指定或使用SQL模式字符'%'或'_'指定一个通配符。一个'%'或空白匹配任何数据库。 Table_name,Column_name 这些列中的值必须是照字面意思的表或列名,不允许模式和空白。某些范围列被服务器视为大小写敏感的,其余不是。这些原则总结在下表中。特别注意Table_name值总是被看作大小写敏感的,即使在查询中的表名的大小写敏感性对待视服务器运行的主机的文件系统而定(UNIX下是大小写敏感,而Windows不是)。
表3 授权表范围列的大小写敏感性列
Host User Password Db Table_name Column_name 大小写敏感性 No Yes Yes Yes Yes No
2.2.2 查询访问验证 每次你发出一个查询,服务器检查你是否有足够的权限执行它,它以user、db、tables_priv和columns_priv的顺序检查,知道它确定你有适当的访问权限或已搜索所有表而一无所获。更具体的说:
服务器检查user表匹配你开始连接的记录以查看你有什么全局权限。如果你有并且它们对查询足够了,服务器则执行它。如果你的全局权限不够,服务器为你在db表中寻找并将该记录中的权限加到你的全局权限中。如果你的全局和数据库级组合的权限不够,服务器继续查找,首先在tables_priv表,然后columns_priv表。如果你在检查了所有表之后仍无权限,服务器拒绝你执行查询的企图。用布尔运算的术语,授权表中的权限被服务器这样使用:
user OR tables_priv OR columns_priv
你可能疑惑为什么前面的描述只引用4个授权表,而实际上有5个。实际上服务器是这样检查访问权限:
user OR (db AND host) OR tables_priv OR columns_priv
第一个较简单的表达式是因为host表不受GRANT和REVOKE语句影响。如果你总是用GRANT和REVOKE管理用户权限,你绝不需要考虑host表。但是其工作原理你用该知道:
当服务器检查数据库级权限时,它对于客户查找db表。如果Host列是空的,它意味着“检查host表以找出哪一个主机能访问数据库”。服务器在host表中查找有与来自db表的记录相同的Db列值。如果没有host记录匹配客户主机,则没有授予数据库级权限。如果这些记录的任何一个的确有一个匹配连接的客户主机的Host列值,db表记录和host表记录结合产生客户的数据库级权限。然而,权限用一个逻辑AND(与)结合起来,这意味着除非一个给定的权限在两个表中都有,否则客户就不具备该权限。以这种方式,你可以在db表中授予一个基本的权限集,然后使用host表对特定的主机有选择地禁用它们。如你可以允许从你的域中的所有主机访问数据库,但关闭了那些?
前面的描述毫无疑问使访问检查听起来一个相当复杂的过程,特别是你以为服务器对你发出的每个查询进行权限检查,然而此过程是很快的,因为服务器其实不从授权表对每个查询查找信息,相反,它在启动时将表的内容读入内存,然后验证查询用的是内存中的副本。这大大提高了访问检查操作的性能。但有一个非常明显的副作用。如果你直接修改授权表的内容,服务器将不知道权限的改变。
例如,如果你用一条INSERT语句向user表加入一个新记录来增加一个新用户,命名在记录中的用户将不能连接服务器。这对管理员新手(有时对有经验的老手)是很困惑的事情,当时解决方法很简单:在你改变了它们之后告诉服务器重载授权表内容,你可以发一条FLUSH PRIVILEGES或执行mysqladmin flush-privileges(或如果你有一个不支持flush-privileges的老版本,用mysqladmin reload。)。
|