MySQL账户和角色基本使用
0. 权限系统
mysql 的privilege 主要是认证 host+user,来决定给它什么privilege,比如SELECT, INSERT, UPDATE, and DELETE
,其他还包括是否允许匿名用户以及能否使用一些函数。
三个无法实现的功能:
- 不能专门指定拒绝某个用户的连接
- 不能允许/拒绝 创建或者删除某数据库中的表,却无法创建/删除该数据库
- 不能对数据库/表等等设置密码, 密码只是属于账户的
用户权限的信息存储在mysql
数据库中的user, db, tables_priv, columns_priv, procs_priv, and global_grants
表内,当mysql启动的时候,从这些表中读取信息加载到内存,用于判断权限信息。
身份识别
每个人的身份是根据连接数据库的host 与用户名的组合, 查看某个用户的权限,使用:
SHOW GRANTS FOR 'joe'@'office.example.com';
SHOW GRANTS FOR 'joe'@'home.example.com';
Mysql连接控制的2个步骤
- 服务器根据是否能够识别该用户来接收或者拒绝连接
- 如果可以连接,那么服务器会检查每一条执行的语句来决定是否该账户有足够的权限运行。
Mysql提供的privilege
Mysql的权限有三种级别:
- Administrative 级别: 让用户能够管理整个mysql 服务的操作
- database级别: 让用户使用一个或者多个数据库以及内部的东西
- database object级别:比如表,索引,视图,存储过程都可以单独设置给用户
Privileges also differ in terms of whether they are static (built in to the server) or dynamic (defined at runtime).
1. 账户
mysql账户和系统账户的关系
- 两个账户没有必然相关性,因为mysql允许使用-u来指定具体的mysql账户来连接服务
- mysql的用户账户允许最长32个字符,系统账户的最大限制各有不同
- mysql账户的密码以加密的方式存储在
user
表中
连接
shell> mysql --user=finley --password db_name
shell> mysql -u finley -p db_name
创建用户和赋予权限
CREATE USER
语句会在mysql.user 表中创建一行,如果没有指定的内容会使用默认值。
-- 匿名用户使用''表示
GRANT ALL ON test.* TO ''@'localhost' ...;
- 基本语法
CREATE USER [IF NOT EXISTS]
user [auth_option] [, user [auth_option]] ...
DEFAULT ROLE role [, role ] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH resource_option [resource_option] ...]
[password_option | lock_option] ...
ALTER USER [IF EXISTS]
user [auth_option] [, user [auth_option]] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH resource_option [resource_option] ...]
[password_option | lock_option] ...
-- 创建新用户并且给与完整权限:
CREATE USER 'yyfyifan'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'yyfyifan'@'%';
mysql> CREATE USER 'finley'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'finley'@'localhost'
-> WITH GRANT OPTION;
mysql> CREATE USER 'finley'@'%' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'finley'@'%'
-> WITH GRANT OPTION;
mysql> CREATE USER 'admin'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';
mysql> CREATE USER 'dummy'@'localhost';
mysql> CREATE USER 'custom'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
-> ON bankaccount.*
-> TO 'custom'@'localhost';
mysql> CREATE USER 'custom'@'host47.example.com' IDENTIFIED BY 'password';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
-> ON expenses.*
-> TO 'custom'@'host47.example.com';
mysql> CREATE USER 'custom'@'%.example.com' IDENTIFIED BY 'password';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
-> ON customer.*
-> TO 'custom'@'%.example.com';
查看账户的权限
SHOW GRANTS; -- 显示所有权限情况
SHOW GRANTS FOR 'admin'@'localhost'; --显示特定用户权限情况
SHOW CREATE USER 'admin'@'localhost'\G --查看非权限信息的部分
删除用户账户
mysql> DROP USER 'jeffrey'@'localhost';
配置密码
只有用户拥有CREATE USER
权限,才允许创建和修改密码; 且如果 read_only
系统变量已激活那么使用账户认证之类的语句比如CREATE USER
orALTER USER
必须还得拥有CONNECTION_ADMIN
or SUPER
权限.
-- 创建时设置密码
CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';
-- 修改密码
ALTER USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';
-- 修改当前用户(非匿名)密码
ALTER USER USER() IDENTIFIED BY 'password';
--使用命令行工具修改密码
mysqladmin -u user_name -h host_name password "password"
2. 角色
可以给账户分配角色,更加方便管理多个同样权限的账户。MySQL主要管理角色的语句如下:
语句 | 作用 |
---|---|
CREATE ROLE and DROP ROLE | 创建和删除角色 |
GRANT and REVOKE | 给角色或者账户分配权限 |
SHOW GRANTS | 显示 账户/角色 所拥有的 权限或者角色 |
SET DEFAULT ROLE | 设置账户默认使用什么角色 |
SET ROLE | 改变当前会话的角色 |
CURRENT_ROLE() 函数 | 显示当前会话的角色 |
mandatory_roles 和activate_all_roles_on_login 系统变量 | 允许定义用户登陆时强制的或者激活授权的角色 |
创建角色
-- 角色名和帐户名相同,也是名字+host,如果没有写host,默认为'%'
CREATE ROLE 'app_developer', 'app_read', 'app_write'; --创建了3个角色
赋予角色权限
GRANT ALL ON app_db.* TO 'app_developer'; -- 给app_db数据库中所有表的所有权限
GRANT SELECT ON app_db.* TO 'app_read'; -- app_db数据库中所有表的查询权限
GRANT INSERT, UPDATE, DELETE ON app_db.* TO 'app_write'; --app_db数据库中所有表的修改权限
赋予账户角色
现有4个用户
CREATE USER 'dev1'@'localhost' IDENTIFIED BY 'dev1pass';
CREATE USER 'read_user1'@'localhost' IDENTIFIED BY 'read_user1pass';
CREATE USER 'read_user2'@'localhost' IDENTIFIED BY 'read_user2pass';
CREATE USER 'rw_user1'@'localhost' IDENTIFIED BY 'rw_user1pass';
赋予角色
GRANT 'app_developer' TO 'dev1'@'localhost';
GRANT 'app_read' TO 'read_user1'@'localhost', 'read_user2'@'localhost';
GRANT 'app_read', 'app_write' TO 'rw_user1'@'localhost';
赋予角色和赋予权限的语句都是GRANT开头,但是区别在于是否由ON,所以 角色和权限,需要分成不同的语句来授予
查看角色的权限
-- 查看账户的权限
SHOW GRANTS FOR 'dev1'@'localhost';
+-------------------------------------------------+
| Grants for dev1@localhost |
+-------------------------------------------------+
| GRANT USAGE ON *.* TO `dev1`@`localhost` |
| GRANT `app_developer`@`%` TO `dev1`@`localhost` |
+-------------------------------------------------+
-- 查看某个账户拥有的某个角色对应的权限
SHOW GRANTS FOR 'rw_user1'@'localhost' USING 'app_read', 'app_write'; --同时看多个角色
SHOW GRANTS FOR 'dev1'@'localhost' USING 'app_developer';
+----------------------------------------------------------+
| Grants for dev1@localhost |
+----------------------------------------------------------+
| GRANT USAGE ON *.* TO `dev1`@`localhost` |
| GRANT ALL PRIVILEGES ON `app_db`.* TO `dev1`@`localhost` |
| GRANT `app_developer`@`%` TO `dev1`@`localhost` |
+----------------------------------------------------------+
撤销角色、收回角色的权力
REVOKE role FROM user; -- 收回该账户的角色
REVOKE INSERT, UPDATE, DELETE ON app_db.* FROM 'app_write'; --收回角色的权力
-- 修改了角色的权利,会影响拥有该角色的账户的权力
删除角色
DROP ROLE 'app_read', 'app_write';
角色和账户互换
角色和账户可以互相替代,比如说把账户赋予账户,角色赋予角色,账户赋予角色,角色赋予账户:
CREATE USER 'u1';
CREATE ROLE 'r1';
GRANT SELECT ON db1.* TO 'u1';
GRANT SELECT ON db2.* TO 'r1';
CREATE USER 'u2';
CREATE ROLE 'r2';
GRANT 'u1', 'r1' TO 'u2';
GRANT 'u1', 'r1' TO 'r2';
这样会把账户的权力和角色,赋予给另一个账户或者角色。
激活角色
角色拥有的权限,需要激活才能形式。
查看当前会话已激活的角色
SELECT CURRENT_ROLE();
设置默认激活的角色
使用SET DEFAULT ROLE
-- 为下面4个用户默认激活所有已拥有的角色
SET DEFAULT ROLE ALL TO
'dev1'@'localhost',
'read_user1'@'localhost',
'read_user2'@'localhost',
'rw_user1'@'localhost';
系统变量配置激活
为了配置默认激活所有角色和强制角色,在配置文件中配置activate_all_roles_on_login
系统变量,默认是disabled。
运行时激活
使用SET ROLE
来设置当前激活哪些角色。
SET ROLE NONE; SELECT CURRENT_ROLE();
SET ROLE ALL EXCEPT 'app_write'; SELECT CURRENT_ROLE();
SET ROLE DEFAULT; SELECT CURRENT_ROLE();
设置强制角色
mandatory role 是给每个创建账户的默认角色,不需要手动设置。强制角色无法被 REVOKE
或者DROP
.
服务启动前设置
[mysqld]
mandatory_roles='role1,role2@localhost,r3@%.example.com'
运行时设置
SET PERSIST mandatory_roles = 'role1,role2@localhost,r3@%.example.com'; --系统重启后仍然有效
SET GLOBAL mandatory_roles = 'role1,role2@localhost,r3@%.example.com'; --系统重启后失效