释放双眼,带上耳机,听听看~!
1. 概述
关于账户权限的信息被存储在系统数据库 mysql 的 user, db, tables_priv, columns_priv 以及 procs_priv 表中。
包含的相关信息如下:
user 用户账户,全局权限和其它非特权列
db 数据库级别的特权
tables_priv 表级特权
columns_priv 列级特权
procs_priv 存储过程和函数权限
2.user
对于 MySQL 用户来说,账户相关的信息被存储在 mysql 数据中的数据表 user 中:
从表中可以知道 user 表是由 Host 和 User 项一起作为主键的,即在 MySQL 中,主机名和用户名一起作为标识来识别用户。
在第一节内容中,讲述了如何连接到 MySQL 服务器,而在对服务器进行访问时,会有一个连接验证的阶段。这个的验证阶段就需要主机名,用户名以及密码等内容进行验证。
这里需要特别强调,主机名和用户名一起作为标识。例如有一台服务器,这时我们有两个客户端分别为 A 和 B。两个客户端都使用用户名为 shiyanlou 的用户登陆,但是由于它们是不同的客户端主机,即使两者使用的用户名相同,它们在连接到服务器端时会被当作两个不同的用户
表中的 Select_priv,Insert_priv,Update_priv等代表该用户是否拥有全局相应操作的特权(privilege),缩写为 priv,即查询,插入,更新的特权。
然后我们查看用户表 mysql.user 的部分信息,如下所示:
可以看到此时系统中的用户都为 root 用户,拥有全局的查询特权。
3.db
而除了全局特权之外,我们还可以指定数据库级别的特权,如下所示:
对于 mysql.db 表来说,Host, Db, User 三者作为表的主键,描述的是用户与数据库的权限。
即用户是否具有对该数据库进行查找,插入,删除等操作的特权。
4.表和列
由于各个表所描述的权限所处的层级不一样,因此一些具体的操作权限也会有区别。因为在上面的内容中,我们并未列出表中的全部字段,所以看不到这一区别。
除了在全局和数据库级别上进行访问权限的限制之外,MySQL 中还提供表级和列级的权限控制,如下所示,分别为 tables_priv 和 colums_priv 的列:
mysql> desc mysql.tables_priv;
mysql> desc mysql.columns_priv;
5.root用户
在实验楼的在线实验环境中,我们并未对 root 用户设置相应的密码,例如刚刚我们查询的 mysql.user 表的信息:
如上图所示,前四个用户为 MySQL 创建的 root 用户,并且 localhost,ubuntu,127.0.0.1和 IPV6 格式的 ::1 都是指向的同一个地址。它们的密码一栏都为空,因为实验环境中并未设置 root 用户的密码。
这里之所以会创建四个用户,是由于实验环境中的 MySQL 版本为 5.5 。而在 5.7 中只会创建一个 root@localhost 的用户。
而最后一个 debian-sys-maint 则为 ubuntu 系统创建的用户,为了方便管理 MySQL 服务在 Ubuntu 中的运行。
除此之外,还可能存在匿名账户,在实验环境中并不存在。
对于没有设置密码的用户,我们使用其连接 MySQL 服务时,不需要使用 -p 参数,如下所示:
6.创建账户
创建账户,一般有两种方式:
使用 MySQL 提供的 CREATE USER 和 GRANT 等语句。(推荐使用的方式)
通过修改 mysql.user 表创建账户
。 CREATE USER
对于创建用户的详细语法较为复杂,这里没有全部列举。
CREATE USER [IF NOT EXISTS]
user IDENTIFIED BY ‘password’;
user 为账户名称,合法的语法为 ‘user_name’@’host_name’,例如 root@localhost
如下所示,我们创建一个名为 syl001@localhost 的账户,密码为 wanneng:
mysql> CREATE USER syl001@localhost IDENTIFIED BY “wanneng”; Query OK, 0 rows affected (0.26 sec)
查询 mysql.user 表,查看 syl001 用户:
直接修改 mysql.user 表
如下所示,我们直接使用 mysql.user 表进行操作,插入一条数据:
上所示,可以看到 syl002 用户添加成功,但是 password 字段显示的是由我们指定的密码 wanneng ,不过这样插入的用户数据并不合法,因为密码字段并没有经过 MySQL 相应的处理,所以使用 wanneng 这个密码和用户名并不能进行合法登录。
7.删除用户
删除用户的语法为:
DROP USER [IF EXISTS] user [, user] …
例如,删除刚刚创建的 syl002@localhost 账户:
mysql> DROP USER “syl002″@”localhost”; Query OK, 0 rows affected (0.00 sec)
此时,再次查看 mysql.user 表,可以发现 syl002@localhost 已经被删除。
8 修改密码
修改用户的密码,由于版本的差异,在 5.7.6 之后,需要使用如下语法: ALTER USER user IDENTIFIED BY ‘new_password’;
在 5.7.6 之前,即实验环境中,使用:
SET PASSWORD FOR user = PASSWORD(‘new_password’);
如下所示,我们为 root 用户设置密码为 123456:
mysql> SET PASSWORD FOR “root”@”localhost” = PASSWORD(“123456”); Query OK, 0 rows affected (0.00 sec)
这时,我们再次查询 mysql.user 表的数据:
需要说明的是,如果在安装 MySQL 的时候分配了 root 密码,那么前四个由 MySQL 创建的用户的密码就会是一样的。
9.授权
在 MySQL 中,我们经常会接触到的有关权限的语句: GRANT 和 REVOKE,它们分别为用户授权和撤销授权。
而在 GRANT 语句中指定的账户不存在时,GRANT 会隐式的创建它。
授权的语法大致如下:
priv_type 代表的是特权权限,部分内容如下图所示,
ALL 代表所有的权限,其它权限都对应着 mysql 数据库的 user,db 等表中的内容。而可选的 [(column_list)] 用于定义了列级权限时使用。
priv_level 代表的是特权级,具体含义如下所示:
*.* 代表全局,即所有的数据库以及数据库中所有的内容
db_name.* 代表数据库,即数据库所有的内容
db_name.tbl_name 即数据库中指定的表
tbl_name 未指定数据库,为默认数据库中的表
db_name.routine_name 存储过程的权限(未涉及)
对于创建的用户 syl001 来说,此时未授予其任何权限。
如下示例:
这时,我们新打开一个终端,避免后面来回切换用户。
然后换到 root 用户的终端,授予其访问 test 表的 name 列的插入和更新的权限。
需要注意的是,如果给予了用户全局的权限,尽管其具备不低于全局的特权级别,如某个数据库的权限,该用户对于该数据库的操作也会被执行。
10.撤销授权
对应 GRANT,撤销授权的语法为 REVOKE:
REVOKE
priv_type [(column_list)]
[, priv_type [(column_list)]] …
ON priv_level FROM user [, user] …
如下示例,撤销 syl001 对于 shiyanlou002.test 表中 name 列的插入权限。需要切换到 root 用户登录的终端:
mysql> REVOKE INSERT(name) ON shiyanlou002.test FROM "syl001"@"localhost"; Query OK, 0 rows affected (0.00 sec)
到 syl001 用户的终端执行。