diff --git a/database/mysql/MYSQL必知必会.md b/database/mysql/MYSQL必知必会.md index 2093953..e723464 100644 --- a/database/mysql/MYSQL必知必会.md +++ b/database/mysql/MYSQL必知必会.md @@ -1536,18 +1536,209 @@ ERROR 1054 (42S22): Unknown column 'aa' in 'field list' 思路,从而减少错误,降低系统维护的成本。 ### 2.5 权限管理:如何控制数据库访问,消除安全隐患? +- 经常会遇到一种需求,就是要根据用户的不同,对数据进行横向和纵向的分组。 +- 所谓横向的分组,就是指用户可以接触到的数据的范围,比如可以看到哪些表的数据;所谓纵向的分组,就是指用户对接触到的数据能访问到什么程度,比如能看、能改,甚至是删除。 +- 我们把具有相同数据访问范围和程度的用户归成不同的类别,这种类别就叫角色。通过角色,管理用户对数据库访问的范围和程度就更加方便了。这也就是对用户的数据访问权限的管理。 +- 恰当的权限设定,可以确保数据的安全性,这是至关重要的。 +- 权限管理: 包括怎么操作角色和用户,怎么通过角色给用户授权,怎么直接给用户授权,从而帮助你管理好用户的权限,提升数据库的安全性。 +- 先讲讲角色。我们可以通过角色对相同权限的用户进行分组管理,这样可以使权限管理更加简单高效。 + +- 角色的作用 +- 角色是在 MySQL 8.0 中引入的新功能,相当于一个权限的集合。引入角色的目的是方便管理拥有相同权限的用户。 +- 超市项目中有库管、营运和财务等不同的模块,它们各自对应不同的数据表。比如库存模块中的盘点表(demo.invcount)、营运模块中的商品信息表(demo.goodsmaster), + 还有财务模块中的应付账款表(demo.settlement)。 + +- 盘点表: +- ![权限管理盘点表](pic/权限管理盘点表.png) +- 商品信息表: +- ![权限商品信息表](pic/权限商品信息表.png) +- 应付账款表: +- ![权限应付账款表](pic/权限应付账款表.png) +- 在超市项目中,员工的职责不同,包括库管、营运和财务等,不同的职责有不同的数据访问权限。比如: + - 张三是库管,他就可以查询商品信息表,对盘点表有增删改查的权限,但无权访问应付账款表; + - 李四是营运,他就拥有对商品信息表有增删改查的权限,而对库存表和应付账款表,只有查看的权限; + - 王五是财务,他就有对应付账款表有增删改查的权限,对商品信息表和库存表,只有查看的权限。 +- 所以,我们需要为每一个职责创建一个对应的角色,为每个员工创建一个对应的数据库用户。然后通过给角色赋予相关的权限,再把角色赋予用户,实现对超市员工访问数据权限 + 的管理,从而保证数据的安全性。 +- 如何操作角色? +- 如何创建角色? +- MySQL 中的角色名称由角色名称加主机名称组成。创建角色的语法结构如下: +```sql +CREATE ROLE 角色名; +``` +- 假设我们现在需要创建一个经理的角色,就可以用下面的代码: +```sql +mysql> CREATE ROLE 'manager'@'localhost'; +Query OK, 0 rows affected (0.06 sec) +``` +- 这里的意思是,创建一个角色,角色名称是“manager”,角色可以登录的主机是“localhost”,意思是只能从数据库服务器运行的这台计算机登录这个账号。你也可以 + 不写主机名,直接创建角色“manager”: +```sql +mysql> CREATE ROLE 'manager'; +Query OK, 0 rows affected (0.01 sec) +``` +- 如果不写主机名,MySQL 默认是通配符“%”,意思是这个账号可以从任何一台主机上登录数据库。 +- 同样道理,如果我们要创建库管的角色,就可以用下面的代码: +```sql +mysql> CREATE ROLE 'stocker'; +Query OK, 0 rows affected (0.02 sec) +``` +- **创建角色之后,默认这个角色是没有任何权限的,我们需要给角色授权。** +- 怎么给角色赋予权限? +- 给角色授权的语法结构是: +```sql +GRANT 权限 ON 表名 TO 角色名; +``` +- 假设我们现在想给经理角色授予商品信息表、盘点表和应付账款表的只读权限,就可以用下面的代码来实现: +```sql +mysql> GRANT SELECT ON demo.settlement TO 'manager'; +Query OK, 0 rows affected (0.03 sec) +mysql> GRANT SELECT ON demo.goodsmaster TO 'manager'; +Query OK, 0 rows affected (0.01 sec) +mysql> GRANT SELECT ON demo.invcount TO 'manager'; +Query OK, 0 rows affected (0.01 sec) +``` +- 如果我们需要赋予库管角色盘点表的增删改查权限、商品信息表的只读权限,对应付账款表没有权限,就可以这样: +```sql +mysql> GRANT SELECT,INSERT,DELETE,UPDATE ON demo.invcount TO 'stocker'; +Query OK, 0 rows affected (0.02 sec) +mysql> GRANT SELECT ON demo.goodsmaster TO 'stocker'; +Query OK, 0 rows affected (0.02 sec) +``` +- 查看角色权限 +- 赋予角色权限之后,我们可以通过 SHOW GRANTS 语句,来查看权限是否创建成功了: +```sql +mysql> SHOW GRANTS FOR 'manager'; ++-------------------------------------------------------+ +| Grants for manager@% | ++-------------------------------------------------------+ +| GRANT USAGE ON *.* TO `manager`@`%` | +| GRANT SELECT ON `demo`.`goodsmaster` TO `manager`@`%` | +| GRANT SELECT ON `demo`.`invcount` TO `manager`@`%` | +| GRANT SELECT ON `demo`.`settlement` TO `manager`@`%` | ++-------------------------------------------------------+ +4 rows in set (0.00 sec) +``` +- 只要你创建了一个角色,系统就会自动给你一个“USAGE”权限,意思是连接登录数据库的权限。代码的最后三行代表了我们给角色“manager”赋予的权限,也就是对商品信息 + 表、盘点表和应付账款表的只读权限。 +- 再来看看库管角色的权限: +```sql +mysql> SHOW GRANTS FOR 'stocker'; ++----------------------------------------------------------------------------+ +| Grants for stocker@% | ++----------------------------------------------------------------------------+ +| GRANT USAGE ON *.* TO `stocker`@`%` | +| GRANT SELECT ON `demo`.`goodsmaster` TO `stocker`@`%` | +| GRANT SELECT, INSERT, UPDATE, DELETE ON `demo`.`invcount` TO `stocker`@`%` | ++----------------------------------------------------------------------------+ +3 rows in set (0.00 sec) +``` +- 结果显示,库管角色拥有商品信息表的只读权限和盘点表的增删改查权限。 +- 当我们需要对业务重新整合的时候,可能就需要对之前创建的角色进行清理,删除一些不会再使用的角色。 +- 删除角色 +- 删除角色的操作很简单,你只要掌握语法结构就行了。 +```sql +DROP ROLE 角色名称; +``` +- 如何操作用户? +- 我们可以把数据库中的角色看作是一个权限集。角色本身不能操作数据,这个任务还是要靠用户来完成。在操作用户前,我们先要创建一个用户。 +- 创建用户 +- 创建用户的语法结构是这样的: +```sql +CREATE USER 用户名 [IDENTIFIED BY 密码]; +``` +- “[ ]”表示可选,也就是说,可以指定用户登录时需要密码验证,也可以不指定密码验证,这样用户可以直接登录。不过,不指定密码的方式不安全,不推荐使用。 +- 举个例子,假设我们要给张三创建一个用户,用户名是“zhangsan”,密码是“mysql”,可以通过下面的代码来实现: +```sql +mysql> CREATE USER 'zhangsan' IDENTIFIED BY 'mysql'; +Query OK, 0 rows affected (0.02 sec) +``` +- 这样,张三的用户就创建成功了。 +- 给用户授权 +- 给用户授权的方式有 2 种,分别是通过把角色赋予用户给用户授权,和直接给用户授权。 +- 通过把角色赋予用户给用户授权的语法结构如下: +```sql +GRANT 角色名称 TO 用户名称; +``` +- 举个小例子,我们想要给张三赋予库管的角色,可以通过下面的代码实现: +```sql +mysql> GRANT 'stocker' TO 'zhangsan'; +Query OK, 0 rows affected (0.01 sec) +``` +- 我们也可以直接给用户授权,语法结构如下: +```sql +GRANT 权限 ON 表名 TO 用户名; +``` +- 这种方式简单直接,我就不多说了。下面我们来查看一下这个用户的权限有哪些。 +- 查看用户权限 +- 查看用户权限的语法结构是: +```sql +SHOW GRANTS FOR 用户名; +``` +- 我们可以通过下面的代码来查看张三的权限: +```sql +mysql> SHOW GRANTS FOR 'zhangsan'; ++---------------------------------------+ +| Grants for zhangsan@% | ++---------------------------------------+ +| GRANT USAGE ON *.* TO `zhangsan`@`%` | +| GRANT `stocker`@`%` TO `zhangsan`@`%` | ++---------------------------------------+ +2 rows in set (0.00 sec) +``` +- 结果显示,张三拥有库管角色的权限。 +- 提醒你一个常见的坑。 +- 如果现在你用张三的这个用户去登录,你会发现,这个账号是没有任何权限的。你是不是觉得很奇怪,我不是把角色“stocker”赋予用户“zhangsan”了吗?那用 + 户“zhangsan”应该有角色“stocker”的权限啊。其实,这是因为,MySQL 中创建了角色之后,默认都是没有被激活的,也就是不能用,必须要用下面的语句激活: +```sql +SET global activate_all_roles_on_login=ON; +``` +- 这条 SQL 语句的意思是,对所有角色永久激活。运行这条语句之后,用户“zhangsan”才真正拥有了角色“stocker”的所有权限。 +- 下面我们就用张三的账号登录,确认一下他有没有相应的权限: +```sql +H:\>mysql -u zhangsan -p +Enter password: ***** +Welcome to the MySQL monitor. Commands end with ; or \g. +Your MySQL connection id is 24 +Server version: 8.0.23 MySQL Community Server - GPL +Copyright (c) 2000, 2021, Oracle and/or its affiliates. +Oracle is a registered trademark of Oracle Corporation and/or its +affiliates. Other names may be trademarks of their respective +owners. +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. +mysql> select * from demo.goodsmaster; ++------------+---------+-----------+---------------+------+------------+------ +| itemnumber | barcode | goodsname | specification | unit | salesprice | avgim ++------------+---------+-----------+---------------+------+------------+------ +| 1 | 0001 | 书 | 16开 | 本 | 89.00 | 31.00 | +| 2 | 0002 | 笔 | NULL | 包 | 5.00 | 2.87 | ++------------+---------+-----------+---------------+------+------------+------ +2 rows in set (0.02 sec) +``` +- 结果显示,我们可以正常登录,并且可以查询商品信息表的内容。 +- 删除用户 +- 当用户不再使用的时候,我们也可以删除用户。操作起来很简单,你只要知道语法结构就行了: +```sql +DROP USER 用户名; +``` - - +- 总结 +- 角色是权限的集合。你可以直接给用户授予访问数据库的权限,也可以通过把角色授予用户,从而把角色对数据库的访问权限全部授予给用户。而用户是数据库的使用者,我们可 + 以通过给用户授予访问数据库中资源的权限,来控制使用者对数据库的访问,消除安全隐患。 +- 需要注意的是,角色在刚刚创建出来的时候,默认是没有激活的,需要手动激活,才可以使用。如果你把角色赋予了用户,那么用户就拥有了角色的全部权限。但是,如果你删除 + 了角色,那么用户也就失去了通过这个角色所获得的所有权限。 +- 有一些程序员喜欢使用 Root 超级用户来访问数据库,完全把权限控制放在应用层面实现。这样当然也是可以的。不过我建议你,尽量使用数据库自己的角色和用户机制 + 来控制访问权限,不要轻易用 Root 账号。因为 Root 账号密码放在代码里面不安全,一旦泄露,数据库就会完全失去保护。而且,MySQL 的权限控制功能十分完善,应该尽量利 + 用,可以提高效率,而且安全可靠。 diff --git a/database/mysql/pic/权限商品信息表.png b/database/mysql/pic/权限商品信息表.png new file mode 100644 index 0000000..e6c2aa5 Binary files /dev/null and b/database/mysql/pic/权限商品信息表.png differ diff --git a/database/mysql/pic/权限应付账款表.png b/database/mysql/pic/权限应付账款表.png new file mode 100644 index 0000000..a00ae7e Binary files /dev/null and b/database/mysql/pic/权限应付账款表.png differ diff --git a/database/mysql/pic/权限管理盘点表.png b/database/mysql/pic/权限管理盘点表.png new file mode 100644 index 0000000..dcb5f28 Binary files /dev/null and b/database/mysql/pic/权限管理盘点表.png differ