56 mysql 用户权限相关的实现
前言
这里讨论 mysql 的权限相关处理
使用如下语句创建 tz_test 用户, 并赋予他 test_02 数据库的查询权限
create user 'tz_test'@'%' identified by 'tz_test';
grant select on test_02.* to 'tz_test'@'%';
查询目标数据表, 数据如下, tz_test_02
UPDATE command denied to user 'tz_test'@'192.168.220.1' for table 'tz_test_02'
执行 update 之后, 客户端这边 得到的信息如下
这里对于当前用户 tz_test 访问 tz_test_02 数据表 验证在这里, 由于上面 check_grant 这边验证 tz_test 用户没有 test_02.tz_test_02 的 UPDATE 权限, 这里是响应的错误信息给客户端 “UPDATE command denied to user 'tz_test'@'192.168.220.1' for table 'tz_test_02'”
首先看一下 各个权限的标志, 分别对应于 SELECT, INSERT, UPDATE, DELETE, CREATE, DROP 等等各个权限
结合这里的上下文, 我们可以看到的是 tz_test 用户在 192.168.220.1 上面访问 mysql 服务器
期望 对 test_02 库的 tz_test_02 表 执行 UPDATE 相关操作
然后这里 tz_test@192.168.220.1 对于 test_02.tz_test_02 的权限仅仅只有 SELECT 权限
然后 table_hash_search 是查询 是否有 数据库表粒度的权限配置, 这部分的配置是持久化在 mysql.tables_priv 中, 然后加载到了 column_priv_hash 中, table_hash_search 中查询到的 HASH 是 column_priv_hash
如果 上面数据库粒度的 UPDATE 权限也没有, 然后 这里具体到某张表粒度的权限也没有, 那么就是 当前用户在当前主机上 没有访问 目标数据库的目标数据表 的 更新权限
然后 走了后面的 “goto err” 响应错误信息给客户端
获取 tz_test@192.168.220.1 访问 test_02.tz_test_02 的权限的地方
这里是从 thd->security_context()->db_access() 获取的数据
thd->security_context()->db_access() 是来自于切换数据库的时候, 有更新 当前用户@当前主机 访问目标数据库 的权限信息
acl_get 通过 user@host -> db 去从 mysql.db 中获取 权限信息
然后 下面 mysql_change_db_impl 更新权限信息到 thd->m_security_ctx->m_db_access
acl_get 中遍历 acl_dbs 列表去查询 user@host -> db 的认证信息
三层比较, user, ip, db, 对应的就是 user@host -> db
设置当前 session[user@host] 访问 目标数据库 的权限信息
以上就是整体流程
切换数据库的时候, 会从 acl_dbs[对应的是 mysql.db 的数据] 中查询 user@host -> db 的认证信息, 保存到当前 session 的上下文
然后 业务查询过来了之后, check_access 将该认证信息 传递到 table->grant->db_access
然后 check_grant 中来做具体的权限校验
如果 数据库权限中没有该权限, 并且 数据表权限 中没有该权限, 则响应 TABLEACCESS_DENIED_ERROR
acl_dbs 的加载
遍历的是 mysql.db 这张数据表, 然后来加载数据, 之后放到 acl_dbs
get_access 中获取的是当前记录行的各个标记组成的 access 数字
主要就是 (user@host -> db) -> access 的一个映射
获取 access 的方式如下
遍历各个 权限表示的字段, 加上各自的权重, 然后组成 access
column_priv_hash 的加载
这里面加载的是 mysql.tables_priv 数据表, 对应的是 (user@host -> db@tableName) -> access 的一个映射, 数据是维护熬了 column_priv_hash 中
如下是 初始化的操作, 遍历 mysql.tables_priv 的记录信息, 封装成为 GRANT_TABLE 数据, 然后将数据插入到 column_priv_hash 中
然后 使用是在 check_grant 中使用的
根据 mysql.tables_priv 记录信息, 创建 GRANT_TABLE 的信息
主要是 (user@host -> db@tableName) -> access
完