谁能看成绩,谁能改成绩?
引例 学校的教务数据库
教务数据库里存着全校学生的成绩,也存着老师的工资。学生只能查成绩,不能改;辅导员要看学生信息,却不该看到老师的工资;任课老师要录成绩……
同一个数据库,不同的人能做的事不一样。这一章就学:怎样让 MySQL 照着演示里这张权限表办事。
数据库自身的安全手段有好几种:用户标识与鉴定、存取权限控制、视图、数据加密、安全审计。本章在 MySQL 中做前两件:管用户、管权限。
| 查成绩 | 改成绩 | 查学生信息 | 查教师工资 | |
|---|---|---|---|---|
| 学生 | ✓ | ✗ | ✗ | ✗ |
| 辅导员 | ✓ | ✗ | ✓ | ✗ |
| 任课教师 | ✓ | ✓ | ✓ | ✗ |
| 教务员 | ✓ | ✓ | ✓ | ✓ |
两道关:先认人,再看权限
引例 进实验楼要刷两次卡
在楼门口刷一次校园卡,证明你是本校的人;到了某间机房门口,还要再刷一次,看你有没有这间房的权限。只过了大门,照样进不了机房。
MySQL 也是这样把关的:登录一次,之后每条语句都查一次。
登录:用户名、主机、口令三样都对得上,才能连进来。对不上:报错 1045,连接被拒绝。
权限:每条语句执行前,先查有没有这项权限。没有权限:报错 1142,这条语句不执行。
用户和权限都记在系统库 mysql 的几张表里:用户在 mysql.user,库、表、字段的权限分别在 mysql.db、mysql.tables_priv、mysql.columns_priv。后面学的语句,其实都在改这几张表。
用户:账户 = 用户名 + 主机
引例 新来的助教小李
学期初来了一位新助教小李,要用教务数据库。第一件事是给他开个账号,就像入职先办一张工卡:卡上写着名字,也写着在哪儿能刷——只在办公室,还是哪个校区都行。
开账号、改口令、改名、销号,就是这一步的五条语句。
'用户名'@'主机'。新建的用户只能登录,还用不了任何数据。| 写法 | 意思 |
|---|---|
| 'localhost' | 只能在数据库服务器这台电脑上登录 |
| '%' | 任何电脑都能登录 |
| 不写 @主机 | 等于写 '%' |
- 创建CREATE USER 'xiaoli'@'localhost' IDENTIFIED BY 'xl123';
- 查看SELECT User, Host FROM mysql.user;
- 改口令ALTER USER 'xiaoli'@'localhost' IDENTIFIED BY 'xl456';
- 改名RENAME USER 'xiaoli'@'localhost' TO 'lijing'@'localhost';
- 删除DROP USER 'lijing'@'localhost';
注意用户名、主机、口令都要加单引号。不要用 INSERT、UPDATE 直接改 mysql.user 表来建用户、改口令。
'xiaoli'@| User | Host | 口令(加密后保存) |
|---|
授权:GRANT 权限 ON 范围 TO 用户
引例 工卡办好了,可门都打不开
小李的账号建好了,可他一登录,什么表都查不了——还没给他开通权限。教务处决定:teaching 库的表他都能查,但只能修改成绩表。
「能做什么」「在哪儿做」「给谁」,正好是一条 GRANT 的三段。
*.* 所有库 › 库名.* 一个库 › 库名.表名 一张表 › 字段。| ON 后面写 | 管多大 | 记在 |
|---|---|---|
| *.* | 所有库(全局) | mysql.user |
| teaching.* | teaching 库的全部表 | mysql.db |
| teaching.sc | 只有成绩表 sc | mysql.tables_priv |
| SELECT(tno, tn) | 只有 tno、tn 两列 | mysql.columns_priv |
注意先 CREATE USER,再 GRANT,否则报错 1410。末尾加 WITH GRANT OPTION,对方还能把这些权限再授给别人。
查看与收回:SHOW GRANTS 和 REVOKE
引例 小李调岗了
学期末小李改带实验课,不再管成绩了。账号不用删,只要把「修改成绩」这项权限关掉。先看看他现在有哪些权限,再收回多余的那项。
查看用 SHOW GRANTS,收回用 REVOKE。
TO 换成 FROM。- 查看SHOW GRANTS FOR 'xiaoli'@'localhost';
结果中一行就是一条授权。第一行 USAGE 表示「只能登录」,每个用户都有。
- 全收回REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'xiaoli'@'localhost';
注意在哪一层授的,就在哪一层收:在 teaching.sc 上授的权限,要写 ON teaching.sc 才收得回。
角色:把一组权限打包,分给很多人
引例 新学期来了 30 位老师
每位老师都要同样的 4 项权限。一位位 GRANT,要写 120 条;下学期再加一项,又得改 30 遍。能不能先做一张「任课教师」权限模板,人来了直接套上?
这张模板就是角色。
- 1 建角色CREATE ROLE 'teacher';
- 2 授权GRANT SELECT, INSERT, UPDATE, DELETE ON teaching.sc TO 'teacher';
- 3 分给用户GRANT 'teacher' TO 'teacher2'@'localhost', 'teacher3'@'localhost';
- 4 激活SET DEFAULT ROLE 'teacher' TO 'teacher2'@'localhost', 'teacher3'@'localhost';
- 撤销REVOKE 'teacher' FROM 'teacher2'@'localhost';
注意第 3 步没有 ON。用户登录后执行 SELECT CURRENT_ROLE();,结果是 NONE 就说明角色还没激活。
teacherSELECT * FROM teaching.sc;报错 1142