提 到 权 限, 通 常 都 是 用 户 A 拥 有 对 象 B 的 权 限, 很 多 朋 友 想 必 已 经 对 此 形 成 了 思 维 定 势, 毕 竟 像 Oracle 或 SQL Server 这 类 大 型 数 据 库 软 件 中 的 权 限 验 证, 也 都 是 如 此 设 定, 指 定 甲 用 户 拥 有 操 作 乙 对 象 的 权 限 而 MySQL 数 据 库 的 权 限 验 证 在 设 计 阶 段 就 体 现 的 有 所 不 同, 它 在 这 中 间 又 加 了 一 级 维 度, 变 成 从 丙 处 来 的 那 个 甲 拥 有 访 问 乙 的 权 限 可 能 有 些 同 学 一 下 子 转 不 过 弯 来, 那 我 换 一 个 角 度 来 描 述 : 甲 只 有 从 丙 处 连 接 过 来, 才 能 够 访 问 对 象 乙 这 样 对 比 的 话, 是 否 又 跟 Oracle/SQL Server 这 类 数 据 库 的 身 份 验 证 机 制 比 较 相 似 了 呢, 只 是 如 Oracle 这 类 数 据 库 软 件, 默 认 是 不 加 丙 这 一 层 的 ( 如 果 想 加 当 然 也 可 以 支 持 ), 而 在 MySQL 中, 丙 ( 来 源 ) 成 了 一 个 必 选 项, 也 就 是 说, 对 于 MySQL 数 据 库, 甲 的 身 份 当 然 重 要, 但 甲 从 哪 儿 来 的 也 同 样 重 要, 即 使 同 样 叫 甲, 从 A 处 来 和 从 B 处 来 的 甲 的 权 限 可 以 不 同, 甚 至 应 该 视 作 是 两 个 不 同 的 用 户 在 本 章 正 式 开 始 前 先 描 述 这 样 一 段, 并 不 是 想 说 MySQL 有 多 么 高 级 或 先 进, 只 是 想 表 达 这 样 一 种 看 法,MySQL 确 实 有 所 不 同 OK, 接 下 来, 跟 随 三 思 一 起, 进 入 MySQL 的 权 限 世 界 吧! 5.1 谈 谈 权 限 处 理 逻 辑 所 有 权 限 认 证 的 根 本 目 的, 都 是 为 了 让 用 户 只 能 做 允 许 它 做 的 事 情,MySQL 也 不 例 外, 大 家 ( 泛 指 数 据 库 产 品 ) 实 现 的 原 理 也 都 差 不 多, 只 不 过 机 制 上 稍 有 差 异, 在 权 限 粒 度 控 制 上 有 所 不 同 MySQL 数 据 库 服 务 采 用 的 是 白 名 单 的 权 限 策 略, 也 就 是 说, 明 确 指 定 了 哪 些 用 户 能 够 做 什 么, 但 没 法 明 确 地 指 定 某 些 用 户 不 能 做 什 么, 对 权 限 的 验 证 主 要 是 通 过 mysql 库 下 的 几 个 数 据 字 典 表, 来 实 现 不 同 粒 度 的 权 限 需 求, 关 于 这 几 个 字 典 表 后 面 会 有 章 节 详 细 介 绍 这 里 简 要 介 绍 其 处 理 逻 辑,MySQL 在 检 查 用 户 连 接 时 可 以 分 为 两 个 阶 段 5.1.1 能 不 能 连 接 当 用 户 发 出 请 求 尝 试 连 接 MySQL 服 务 时,MySQL 首 先 是 检 查 登 录 用 户 的 相 关 信 息, 比 如 发 起 登 录 请 求 的 主 机 名 是 否 匹 配 登 录 使 用 的 用 户 名 或 密 码 是 否 正 确, 如 果 这 一 关 过 不 去, 那 连 接 就 直 接 被 拒 绝 了, 常 见 的 登 录 失 败 信 息 ERROR 1045 (28000): Access denied
for user '...', 就 是 在 这 个 阶 段 的 验 证 未 通 过 抛 出 的 错 误 提 示 MySQL 数 据 库 验 证 权 限 有 3 个 维 度 : 我 是 谁 从 哪 儿 来 到 哪 儿 去 ( 真 像 哲 学 家 探 讨 人 生 的 终 极 命 题 呀 ) 这 3 个 维 度 中, 前 两 个 决 定 能 不 能 连 接, 就 是 说 验 证 用 户 的 身 份 是 否 合 法, 本 步 通 过 之 后, 才 会 涉 及 能 不 能 访 问 目 标 对 象 的 环 节 在 MySQL 数 据 库 中 验 证 用 户, 需 要 检 查 3 项 值 : 用 户 名 用 户 密 码 和 来 源 主 机, 这 3 项 信 息 的 正 确 值 ( 创 建 用 户 时 指 定 ), 保 存 在 mysql 库 中 的 user 表 对 象 内, 分 别 对 应 user 表 对 象 中 的 user password 和 host 三 列 如 果 事 先 看 过 user 表 中 这 几 列 的 定 义, 会 发 现 MySQL 的 设 计 非 常 有 意 思, 这 3 列 居 然 都 可 以 为 空 ( 注 意 不 是 NULL 值 ), 这 也 是 某 些 场 景 里 登 录 MySQL 数 据 库 不 需 要 输 入 用 户 名 或 不 需 要 输 入 密 码 的 原 因 5.1.2 能 不 能 执 行 操 作 连 接 到 数 据 库 之 后, 能 不 能 执 行 操 作, 比 如 说 建 库 建 表 改 表, 查 询 或 修 改 数 据 等, 这 个 阶 段 涉 及 的 因 素 ( 对 象 ) 要 复 杂 一 点 点, 除 了 上 面 提 到 的 mysql.user 字 典 表 起 作 用 外, 另 外 还 有 mysql.db mysql.tables_priv mysql.columns_priv mysql.proc_priv( 事 实 上 在 5.6.10 版 本 以 前, 还 有 mysql.host 表, 不 过 之 后 版 本 中,host 表 已 经 明 确 被 废 弃, 其 实 在 之 前 版 本 里 它 也 没 什 么 用, 原 本 就 是 被 判 了 死 缓, 现 在 缓 期 过 完 了, 不 过 没 有 转 为 无 期, 而 是 直 接 执 行 死 刑 ) 几 个 字 典 表 来 对 数 据 库, 或 针 对 对 象 甚 至 是 对 象 列 做 更 细 粒 度 的 控 制 这 些 字 典 表 虽 说 各 有 分 工, 但 相 互 之 间 在 权 限 分 配 上 还 是 会 有 一 定 的 重 合, 比 如 说 tables_priv 字 典 表 一 看 就 知 道 是 专 门 针 对 表 对 象 的 权 限 明 细, 不 过 user 表 和 db 表 中 也 可 以 授 予 用 户 操 作 表 对 象 的 权 限 那 么 MySQL 服 务 是 怎 么 来 区 分 这 些 权 限 的 呢? 我 的 个 人 理 解, 总 的 原 则 仍 然 是 按 照 粒 度 比 如 要 执 行 对 整 个 数 据 库 服 务 的 管 理 操 作, 那 么 一 定 是 根 据 user 表 中 的 记 录 验 证 权 限 是 否 匹 配, 因 为 只 有 这 个 表 是 针 对 MySQL 服 务 全 局 的 ; 如 果 请 求 某 个 明 确 的 数 据 库 对 象, 比 如 更 新 某 个 表 中 记 录, 那 么 MySQL 服 务 也 仍 然 会 按 照 粒 度 从 粗 到 细 的 方 式, 先 检 查 user 字 典 表 中 全 局 的 设 置, 找 不 到 匹 配 的 话, 则 继 续 检 查 db 字 典 表 这 样 的 方 式 ; 一 旦 在 某 个 粒 度 匹 配 到 合 适 的 权 限, 就 允 许 用 户 执 行, 否 则 继 续 查 询 更 细 的 粒 度 表 ; 如 果 所 有 的 粒 度 滤 过 一 遍, 还 是 没 能 匹 配 到 合 适 的 权 限, 那 么 用 户 的 操 作 就 会 被 拒 绝 了 通 过 上 述 逻 辑 还 可 以 明 确 一 点, 就 是 粒 度 控 制 越 细, 权 限 验 证 上 的 步 骤 就 会 越 多, 相 应 对 性 能 必 然 会 有 影 响, 这 一 点 在 进 行 权 限 分 配 时 务 必 考 虑 在 内 5.1.3 权 限 变 更 何 时 生 效 向 用 户 分 配 的 权 限, 哪 些 情 况 下 会 生 效 呢? 一 般 来 说,MySQL 数 据 库 在 启 动 时 就 会 将 前 面 提 到 的 几 个 权 限 字 典 表 中 的 内 容 读 到 内 存 里, 当 有 用 户 连 接 或 执 行 操 作 时, 根 据 内 存 中 的 数 据 来 检 查 用 户 是 否 有 权 限 执 行 相 应 的 操 作 注 意, 如 果 你 读 的 足 够 认 真 并 且 大 脑 持 续 在 进 行 思 考, 这 会 儿 应 该 会 产 生 这 样 的 一 个
疑 问 : 如 果 用 户 连 接 上 数 据 库 后, 管 理 员 对 该 用 户 的 权 限 进 行 了 修 改 操 作, 是 否 即 时 生 效 呢? 针 对 这 个 问 题, 答 案 是 : 看 情 况! 如 果 是 通 过 GRANT REVOKE SET PASSWORD RENAME USER 等 MySQL 提 供 的 命 令 执 行 修 改, 那 么 权 限 将 马 上 生 效, 因 为 这 些 命 令 将 触 发 系 统 重 新 载 入 授 权 表 (GRANT TABLES) 到 内 存 如 果 是 手 动 修 改 字 典 表 方 式 (INSERT UPDATE DELETE), 没 错,MySQL 中 可 以 手 动 修 改 字 典 表 中 的 记 录 达 到 变 更 用 户 权 限 的 目 的, 但 这 种 情 况 下 权 限 并 不 会 马 上 生 效, 除 非 重 启 MySQL 服 务, 或 者 DBA 主 动 触 发 授 权 表 的 重 新 装 载 问 题 又 来 了, 授 权 表 被 重 新 加 载 后, 对 当 前 已 连 接 的 客 户 端 又 会 产 生 哪 些 影 响 呢? 具 体 如 下 : 表 或 列 粒 度 的 权 限 将 在 客 户 端 下 次 执 行 操 作 时 生 效 数 据 库 级 的 权 限 将 在 客 户 端 执 行 USE db_name 语 句, 切 换 数 据 库 时 生 效 全 局 权 限 和 密 码 修 改, 对 当 前 已 连 接 的 客 户 端 无 效, 下 次 连 接 时 才 会 生 效 5.2 权 限 授 予 与 回 收 当 前 MySQL 就 剩 system 一 个 系 统 管 理 员 账 户 了, 完 全 不 符 合 业 务 需 求 啊, 怎 么 办 呢, 本 节 就 来 着 重 演 示 MySQL 数 据 库 中 如 何 创 建 用 户 分 配 权 限 及 回 收 权 限 在 MySQL 数 据 库 里 对 于 用 户 权 限 的 授 予 和 解 除 比 较 灵 活, 既 可 以 通 过 专 用 命 令, 也 可 以 通 过 直 接 操 作 字 典 表 来 实 现, 正 所 谓 条 条 道 路 通 目 标 不 过 话 说 回 来, 修 的 马 路 多 不 叫 奇 迹, 何 况 在 这 片 神 奇 的 土 地, 奇 迹 这 个 词 本 身 就 是 奇 迹, 因 此 三 思 真 是 不 好 意 思 用 奇 迹 这 样 的 词 来 形 容 : 这 样 想 象 不 到 的 不 平 凡 的 事 ( 注 : 该 段 描 述 为 现 代 汉 语 词 典 中 关 于 奇 迹 一 词 的 解 释 ), 因 此, 我 决 定 用 一 种 加 强 的 语 气 来 描 述 我 的 感 受 : 比 奇 迹 更 神 奇 的 是, 这 条 条 大 路 居 然 都 修 成 了 高 速 路 比 神 奇 的 奇 迹 更 神 奇 的 是, 这 些 高 速 路 居 然 都 是 免 费 的 比 神 奇 的 神 奇 奇 迹 更 神 奇, 那 就 是 神 迹 啊, 额 地 神 哪, 免 费 的 高 速 路 居 然 也 不 堵 车, 这 肯 定 不 是 二 环 三 环 和 四 环, 当 然 跟 G6/G8 线 应 该 也 没 啥 关 系, 至 少 也 是 十 八 环 外 了, 弟 兄 们, 走 吧, 跟 着 三 思 去 溜 达 溜 达 ~~~ 再 次 提 示 很 多 Linux/UNIX 下 管 理 MySQL 数 据 库 服 务 的 DBA, 初 看 到 数 据 库 的 管 理 账 户 root 就 发 蒙 了, 以 为 这 是 什 么 重 要 的 征 兆, 其 实 是 大 可 不 必 的 此 root 非 彼 root,mysql 数 据 库 里 的 root 账 户 跟 操 作 系 统 中 的 root 没 有 丝 毫 的 关 联, 只 是 数 据 库 初 始 化 时 自 动 创 建 的 一 个 名 称 而 已 在 本 书 第 3 章 初 始 化 数 据 库 时, 三 思 已 经 手 动 将 该 用 户 更 名 为 了 system, 我 们 的 操 作 能 够 成 功, 并 且 未 对 后 续 数 据 库 的 正 常 管 理 带 来 任 何 异 常, 也 说 明 root 这 个 账 户 名 不 具 备 什 么 特 殊 的 含 义, 完 全 可 以 随 意 处 理
基 于 合 适 的 用 户 做 符 合 其 权 限 的 事 的 目 的, 执 行 与 权 限 相 关 操 作 的 用 户 当 然 也 得 有 权 限, 默 认 我 们 使 用 的 是 系 统 管 理 员 账 户, 就 是 system 用 户 了, 本 例 中 所 做 的 用 户 管 理 操 作, 如 非 特 别 注 明, 均 是 使 用 mysql 中 的 system 用 户 执 行 5.2.1 创 建 用 户 在 创 建 用 户 之 前, 首 先 说 明 两 点 : 用 户 名 的 长 度 不 能 超 过 16 个 字 符 用 户 名 和 密 码 对 大 小 写 敏 感, 也 就 是 说,Jss 和 jss 是 两 个 不 同 的 用 户, 密 码 也 是 如 此 1. 传 统 方 式 创 建 MySQL 中 专 用 的 创 建 用 户 的 命 令 是 CREATE USER, 该 命 令 语 法 如 下 : CREATE USER user_specification [, user_specification]... user_specification: user [ IDENTIFIED BY [PASSWORD] 'password' IDENTIFIED WITH auth_plugin [AS 'auth_string'] ] CREATE USER 命 令 是 最 传 统 的 创 建 用 户 方 式, 语 法 看 起 来 还 是 挺 简 单 的, 不 过 事 实 上 与 用 户 权 限 相 关 的 细 节 非 常 有 讲 究, 因 为 简 单, 所 以 灵 活, 因 为 灵 活, 所 以 可 配 置 性 强, 因 为 可 配 置 性 强, 所 以 细 节 很 重 要 不 过, 刚 开 始 接 触 时, 大 家 倒 是 不 用 关 注 太 多, 从 易 到 难 嘛, 咱 们 先 按 照 最 简 单 的 方 式 创 建 一 个 名 为 jss 的 用 户 吧, 执 行 操 作 如 下 : (system@localhost) [mysql]> create user jss; Query OK, 0 rows affected (0.01 sec) 你 猜 怎 么 着, 成 功 了! 不 要 担 心 0 rows affected 那 个 提 示, 对 于 操 作 用 户 这 类 SQL 语 句, 它 的 返 回 就 是 这 个 样 子, 只 要 不 是 返 回 什 么 ERROR 之 类 提 示, 就 是 成 功 了, 如 果 想 看 到 明 确 的 结 果, 可 以 通 过 查 询 mysql.user 字 典 表 中 的 记 录 验 证 一 下 : (system@localhost) [mysql]> select user,host,password from mysql.user where user='jss'; +------+------+----------+ user host password +------+------+----------+ jss % +------+------+----------+ 1 row in set (0.00 sec) 当 然 啦! 最 好 的 验 证 方 式 仍 然 是 登 录 测 试, 我 们 刚 刚 创 建 的 用 户, 既 没 有 设 置 登 录 的 密 码, 也 没 有 指 定 来 源 主 机, 因 此 该 用 户 可 以 从 任 意 安 装 了 MySQL 客 户 端, 并 能 够 访 问
目 标 服 务 器 的 机 器 上 创 建 连 接 换 台 装 有 MySQL 客 户 端 的 服 务 器 登 录 试 试, 例 如 : [mysql@mysqldb02 ~]$ mysql -ujss -h 192.168.30.243 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 5.6.12-log JSS for mysqltest Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 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. (jss@192.168.30.243) [(none)]> 可 以 看 到 当 前 就 是 以 jss 身 份 连 接 到 30.243 服 务 器 由 于 前 面 创 建 用 户 时 并 没 有 指 定 任 何 密 码, 因 此 连 接 时 无 需 指 定 密 码 即 可 顺 利 登 录 数 据 库 2. 修 改 用 户 密 码 想 必 读 者 朋 友 也 都 看 出 来 了, 这 样 登 录 很 不 安 全, 密 码 可 以 有 那 么 怎 么 给 用 户 设 置 密 码 呢?ALTER USER?NONONO, 我 们 一 般 都 不 会 这 样 干, 甚 至 在 MySQL 5.6.6 版 本 之 前, 根 本 就 没 有 提 供 ALTER USER 这 样 的 语 法 怎 么 会 这 样, 您 是 否 在 心 里 暗 自 问 自 己 这 个 问 题, 其 实 若 对 MySQL 的 用 户 与 权 限 体 系 有 全 面 的 认 识, 就 会 明 白 这 种 设 计, 对 于 MySQL 数 据 库 来 说 是 合 乎 逻 辑 的 MySQL 数 据 库 中 的 用 户 没 有 太 多 属 性, 从 前 面 的 CREATE USER 语 法 就 能 看 得 出 来, 与 用 户 相 关 的 选 项, 除 了 必 须 指 定 的 用 户 名 外, 就 是 一 个 密 码 选 项 ( 唯 一 一 个 选 项 居 然 还 不 是 必 选 项 ) 至 于 用 户 权 限 的 授 予, 则 是 由 单 独 的 SQL 命 令 操 作 ( 后 面 会 介 绍 这 些 命 令 ) 因 此 对 于 用 户 来 说, 可 能 变 更 的 就 是 用 户 的 密 码, 针 对 这 一 点 需 求,MySQL 没 必 要 整 出 一 个 ALTER USER 语 法, 它 只 需 要 单 独 针 对 修 改 密 码 的 操 作, 提 供 一 条 命 令 即 可, 于 是 就 有 了 SET PASSWORD 命 令, 该 命 令 语 法 如 下 : SET PASSWORD [FOR user] = { PASSWORD('some password') OLD_PASSWORD('some password') 'encrypted password' } 比 如, 修 改 jss 用 户 的 密 码 为 5ienet.com, 执 行 命 令 如 下 : (jss@192.168.30.243) [(none)]> set password for jss=password('5ienet.com'); SET PASSWORD 命 令 会 自 动 更 新 系 统 授 权 表, 之 后 再 使 用 jss 用 户 连 接 MySQL 数 据 库, 就 必 须 输 入 密 码 才 行, 否 则 就 会 抛 出 : ERROR 1045 (28000): Access denied for user 'jss'@'192.168.30.203' (using password: NO)
说 一 下 SET PASSWORD 命 令 中 各 选 项 的 功 能 : (1)SET PASSWORD: 固 定 的 语 法 格 式, 照 着 抄 即 可 (2)[FOR user]:for 选 项 用 于 指 定 要 修 改 密 码 的 用 户, 如 果 是 修 改 当 前 用 户 的 密 码, 可 以 不 用 指 定 这 个 选 项, 如 果 要 修 改 其 他 用 户 ( 前 提 是 操 作 者 确 实 有 权 限 ), 那 么 必 须 通 过 FOR 选 项 指 定 要 修 改 的 目 标 用 户, 格 式 为 user@host (3)PASSWORD/OLD_PASSWORD: 这 是 两 个 密 码 专 用 函 数 MySQL 数 据 库 中 用 户 密 码 当 然 不 会 是 以 明 文 的 形 式 保 存, 它 可 不 像 国 内 某 些 专 业 IT 社 区 那 样, 打 着 专 业 旗 号 却 干 出 很 不 专 业 的 事 情 MySQL 中 能 够 查 询 到 的 用 户 密 码 是 按 照 它 自 己 的 加 密 逻 辑 处 理 后 的 字 符 串 形 式 在 修 改 密 码 时, 也 必 须 指 定 加 密 后 的 字 符 形 式 保 存, 否 则 登 录 验 证 就 会 碰 到 异 常 可 是, 都 说 了 是 加 密 后 的 形 式, 那 我 们 又 怎 么 能 知 道 字 符 被 加 密 后 是 什 么 形 式 呢? 这 里 就 要 分 两 点 来 看 : 1 第 一 种 是 用 户 确 实 知 道, 甭 管 它 是 通 过 什 么 方 式 获 得 的 ( 确 实 有 多 种 方 式 ), 那 么 在 指 定 密 码 时 就 可 以 直 接 指 定 其 加 密 后 的 形 式 2 第 二 种 是 用 户 不 知 道 加 密 后 的 字 符 是 什 么, 那 么 就 可 以 由 MySQL 来 帮 助 我 们 生 成, MySQL 数 据 库 提 供 了 相 应 的 函 数 PASSWORD(), 直 接 调 用 该 函 数 即 可, 这 种 方 式 是 最 常 见 的 调 用 方 式, 我 们 前 面 的 示 例 中 也 是 采 用 这 种 方 式 提 示 : 关 于 OLD_PASSWORD() 函 数 这 个 函 数 的 命 名 容 易 产 生 误 解, 看 起 来 仿 佛 是 跟 用 户 的 旧 密 码 有 什 么 关 系, 其 实 不 是 这 样, 它 只 是 为 了 应 对 MySQL 的 版 本 兼 容 性 才 出 现 的 在 4.1 之 前 的 版 本 中,PASSWORD() 函 数 生 成 16 位 长 度 的 加 密 字 符 串, 而 在 之 后 的 版 本 中, 为 了 提 高 安 全 性,MySQL 改 进 了 密 码 的 生 成 算 法, 现 在 生 成 的 为 41 位 长 度 的 加 密 字 符 串, 那 么 就 会 出 现 一 个 兼 容 性 方 面 的 问 题, 当 用 户 使 用 4.1 之 前 的 客 户 端 连 接 MySQL 服 务 时, 就 会 出 现 由 于 加 密 格 式 不 统 一 造 成 的 登 录 失 败 为 了 提 高 兼 容 性,MySQL 新 增 加 了 OLD_PASSWORD() 函 数, 仍 然 采 用 原 始 的 加 密 策 略 生 成 16 位 长 度 的 加 密 字 符 串, 管 理 员 在 设 置 用 户 口 令 时, 就 可 以 使 用 这 个 函 数 生 成 密 码, 使 其 能 够 兼 容 4.1 之 前 版 本 的 MySQL 客 户 端 两 个 函 数 处 理 相 同 字 符 串 的 输 出 如 下 : (jss@192.168.30.243) [(none)]> select password('123456'),old_password('123456'); +-------------------------------------------+------------------------+ password('123456') old_password('123456') +-------------------------------------------+------------------------+ *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 565491d704013245 +-------------------------------------------+------------------------+ 前 面 提 到, 在 5.6.6 版 本 之 前,MySQL 数 据 库 都 没 有 ALTER USER 语 法, 那 么 为 什 么 后 来 又 增 加 了 ALTER USER, 这 个 语 法 又 能 用 来 做 什 么 呢? 为 什 么 增 加 这 个 语 句 我 也 没 想 明 白, 不 过 这 个 语 句 的 功 能 可 能 要 让 很 多 人 打 死 都 猜 不 到 新 增 的 ALTER USER 语 句 的 功 能, 与 其 他 数 据 库 软 件 中 的 ALTER USER 功 能 差 异 巨 大, 一 言 以 蔽 之, 就 是 让 用 户 的 密 码
过 期 注 意 一 定 要 正 确 理 解, 是 密 码 过 期, 而 不 是 用 户 过 期 哟 用 户 仍 然 可 以 用 ( 登 录 ), 只 是 密 码 过 期 后, 无 法 做 任 何 操 作 比 如 说, 我 们 先 将 jss 用 户 密 码 设 置 为 过 期, 执 行 操 作 如 下 : (system@localhost) [mysql]> alter user jss password expire; 而 后 再 以 jss 用 户 登 录, 用 原 始 密 码 仍 然 能 够 登 录 成 功, 但 是 执 行 操 作 就 不 行 喽 : (jss@192.168.30.243) [(none)]> show databases; ERROR 1820 (HY000): You must SET PASSWORD before executing this statement 实 践 过 之 后, 您 是 否 回 忆 起 了 什 么, 或 者 说 您 现 在 应 该 知 道, 第 2 章 RPM 包 方 式 安 装 后 连 接 数 据 库, 必 须 先 修 改 用 户 密 码 才 能 执 行 操 作, 是 如 何 实 现 的 了 吧! 3. 通 过 登 录 主 机 验 证 用 户 话 说 MySQL 数 据 库 中, 用 户 登 录 除 了 验 证 用 户 名 和 密 码 外, 不 是 号 称 还 要 检 查 来 源 主 机 呢 嘛, 怎 么 前 面 的 登 录 操 作, 似 乎 并 未 感 到 有 对 主 机 层 的 验 证 呢? 这 个 嘛, 因 为 创 建 用 户 时 就 没 有 指 定 登 录 主 机 啊, 没 指 定, 默 认 就 是 不 限 制 不 过 这 个 不 限 制 指 的 是 不 做 限 制, 实 际 上 字 典 表 中 还 是 会 有 对 应 的 标 识, 查 询 一 下 mysql.user 字 典 表 中 的 信 息 : (system@localhost) [(mysql)]> select user,host from mysql.user where user='jss'; +------+------+ user host +------+------+ jss % +------+------+ 1 rows in set (0.00 sec) 注 意 到 这 条 记 录 中 host 列 的 值 了 没, 显 示 一 个 %( 百 分 号 ) 熟 悉 SQL 语 法 的 朋 友 都 知 道,% 在 SQL 语 法 中 是 作 为 通 配 符, 代 表 任 意 字 符 串, 在 这 里 出 现 则 代 表 任 意 主 机, 这 个 才 是 前 面 所 说 的 不 限 制 登 录 主 机 的 真 正 原 因 没 错, 主 机 名 可 以 指 定 通 配 符, 规 则 与 标 准 的 SQL 语 法 中 定 义 完 全 相 同 : %: 对 应 任 意 长 度 的 任 意 字 符 _: 对 应 一 位 长 度 的 任 意 字 符 如 果 user 字 典 表 中 的 host 列 值 为 空 或 %, 均 代 表 任 意 主 机 因 此, 如 果 希 望 创 建 的 用 户 只 能 从 某 个 主 机 或 某 个 IP 段 访 问, 那 么 在 创 建 用 户 时, 就 必 须 明 确 指 定 host, 指 定 的 host 既 可 以 是 IP, 也 可 以 是 主 机 名, 或 者 是 可 正 确 解 析 至 IP 地 址 的 其 他 自 定 义 名 称 接 下 来 我 们 尝 试 创 建 一 个 名 为 jss_ip 的 用 户, 并 且 该 用 户 仅 允 许 从 192.168.30.203 的 主 机 连 接 至 MySQL 服 务 端, 执 行 命 令 如 下 : (system@localhost) [(mysql)]> create user jss_ip@'192.168.30.203' identified by 'jss'; 这 样 使 用 jss_ip 用 户 登 录 时, 只 有 从 192.168.30.203 主 机 发 出 登 录 请 求 才 能 成 功, 从 非 192.168.30.203 的 主 机 上, 使 用 jss_ip 用 户 连 接 时, 不 管 密 码 是 否 正 确, 都 会 抛 出 ERROR 1045 (28000): Access denied 错 误 信 息 : $ mysql -ujss_ip -pjss -h 192.168.30.243
ERROR 1045 (28000): Access denied for user 'jss_ip'@'192.168.10.113' (using password: YES) 如 果 希 望 192.168.30.% 网 段 的 主 机 均 能 够 使 用 jss_ip 用 户 连 接, 又 该 如 何 设 置 呢? 这 种 情 况 下 就 该 通 配 符 出 马 了 : (system@localhost) [(none)]> create user jss_ip@'192.168.30.%' identified by 'jss'; 而 后 从 192.168.30.% 网 段 的 任 意 主 机 上 尝 试 连 接 MySQL 服 务 器, 都 能 够 顺 利 登 录 : $ mysql -ujss_ip -pjss -h 192.168.30.243 Welcome to the MySQL monitor. Commands end with ; or \g. 其 他 大 型 数 据 库 软 件, 直 接 指 定 用 户 即 可 登 录 数 据 库, 但 在 MySQL 数 据 库 中, 则 额 外 还 需 要 有 主 机 这 一 维 度, 用 户 和 主 机 ('user'@'host') 组 成 一 个 唯 一 账 户, 登 录 MySQL 数 据 库 时, 实 际 上 是 通 过 账 户 进 行 验 证 由 于 host 能 够 支 持 通 配 符, 使 得 登 录 验 证 时 来 源 主 机 的 部 分 更 加 灵 活, 表 5-1 列 举 了 一 些 user 和 host 的 常 见 组 合, 希 望 能 够 有 助 于 大 家 理 解 表 5-1 用 户 与 主 机 组 合 示 例 user 列 host 列 对 应 连 接 情 况 'jss' 'jss' 'jss' '192.168.1.2' 'www.5ienet.%' 'www.5ienet.com' 使 用 jss 用 户 登 录 时, 只 有 从 192.168.1.2 主 机 发 出 登 录 请 求 才 能 成 功 创 建 连 接 使 用 jss 用 户 登 录 时, 可 以 从 主 机 名 为 www.5ienet.(net/com/cn...) 的 任 意 主 机 创 建 连 接 使 用 jss 用 户 登 录 时, 只 能 从 主 机 名 为 www.5ienet.com 的 主 机 发 出 请 求 才 能 成 功 创 建 连 接 'jss' '%' 可 以 从 任 意 主 机 使 用 jss 用 户 连 接 '' '10.0.0.%' 可 以 从 10.0.0.% 网 段 内 的 任 意 主 机 创 建 连 接, 并 且 无 需 输 入 任 何 用 户 信 息 '' '%' 任 意 主 机 均 可 以 创 建 连 接, 并 且 连 接 过 程 中 无 需 用 户 信 息 大 家 是 否 注 意 到 表 5-1 中 前 几 行 记 录 中 的 用 户 名 都 叫 jss, 不 过 实 际 上 它 们 不 仅 不 是 同 一 条 记 录, 甚 至 不 是 一 个 用 户 因 为 MySQL 数 据 库 是 根 据 'user'@'host' 来 确 认 记 录 是 否 唯 一, user 表 中 每 一 条 记 录 都 是 一 个 独 立 的 账 户, 每 一 个 独 立 的 账 户 都 可 以 拥 有 各 自 的 权 限 设 置 这 种 设 计 对 于 初 接 触 MySQL 数 据 库 的 朋 友 的 确 可 能 带 来 困 扰, 因 为 大 家 一 般 都 只 听 过 有 user, 谁 能 想 到 这 中 间 还 夹 着 一 层 host, 不 过 我 举 个 例 子 大 家 应 该 就 明 白 了 比 如 说 您 有 两 位 同 事, 都 叫 杨 伟 (user), 一 个 从 山 东 (host) 来, 另 一 个 从 山 西 (host) 来, 您 就 知 道 他 们 肯 定 不 是 一 个 人, 这 种 情 况 搁 现 实 生 活 中 叫 重 名, 两 个 确 实 是 各 自 独 立 的 个 体 重 名 说 尽 管 能 够 帮 助 大 家 理 解 user+host 的 组 合, 不 过 朋 友 们 可 能 还 是 会 有 疑 问, 就 是 重 名 所 带 来 的 现 实 尴 尬, 比 方 说 有 可 能 碰 到 你 喊 一 声 美 女, 结 果 一 堆 人 答 应 的 场 景, 那 MySQL 数 据 库 中 会 不 会 出 现 这 种 情 况 呢? 它 又 怎 么 保 证 一 定 是 那 个 你 想 搭 讪 的 姑 娘 回 应 呢? 按 照 我 的 理 解, 拿 这 个 问 题 拷 问 MySQL 的 智 商 实 在 太 难 为 它 了, 别 说 MySQL 搞
不 清 楚, 就 是 换 个 活 生 生 的 人 也 搞 不 定 啊, 因 此, 肯 定 的 答 复 就 是,MySQL 保 证 不 了 不 过 放 心 啦,MySQL 不 会 返 回 一 堆 记 录 让 人 无 所 适 从 的, 因 为 规 矩 是 限 定 死 的 嘛, 只 能 有 一 条 回 应, 当 然 啦, 它 也 不 会 随 随 便 便 挑 一 个 给 你 作 为 一 款 数 据 库 软 件, 严 谨 是 烙 印 在 它 的 基 因 中 的,MySQL 遇 到 这 种 情 况, 会 按 照 既 定 的 规 则 来 处 理, 处 理 的 规 则 归 根 结 底 就 两 个 字 : 排 序, 而 后 从 排 好 序 的 结 果 中 取 第 一 条 记 录 MySQL 在 排 序 时 会 将 最 明 确 的 host 值 放 在 前 面, 比 如 说 某 个 具 体 的 主 机 名 或 IP 地 址 就 非 常 明 确, 而 像 通 配 符 % 就 是 最 不 明 确 的 代 表 ( 它 代 表 任 意 主 机 ), 排 序 时 会 放 在 后 面, 空 字 符 串 '' 尽 管 也 表 示 任 意 主 机, 但 排 序 的 优 先 级 比 '%' 更 低, 它 会 放 在 最 后 对 于 host 相 同 的 记 录,MySQL 会 再 按 照 user 列 中 的 值 排 序, 规 则 与 host 完 全 相 同, 都 是 最 明 确 的 值 放 在 最 前 面 举 例 来 说,user 字 典 表 中 有 下 列 的 记 录 : +-----------+----------+- Host User... +-----------+----------+- % system... % jss... localhost system... localhost... +-----------+----------+- 按 照 MySQL 数 据 库 的 规 则, 排 序 好 之 后 的 结 果 类 似 这 样 : +-----------+----------+- Host User... +-----------+----------+- localhost system... localhost... % jss... % system... +-----------+----------+- 提 示 排 序 是 什 么 时 候 做 的 呢? 要 知 道,MySQL 在 服 务 启 动 时 就 会 将 user 表 读 取 到 内 存 中, 在 读 取 的 过 程 中 就 会 排 序 MySQL 服 务 运 行 过 程 中, 修 改 用 户 权 限 触 发 权 限 更 新 时, 会 刷 新 内 存 中 的 字 典 表, 这 期 间 又 会 进 行 排 序, 也 就 是 内 存 中 的 字 典 表 永 远 都 是 排 好 序 的 客 户 端 创 建 连 接 时 使 用 的 用 户 名 和 主 机, 有 可 能 同 时 匹 配 user 表 中 的 多 条 记 录 在 上 面 给 出 的 例 子 中, 使 用 system 用 户 登 录 就 有 可 能 既 匹 配 system@'localhost', 又 匹 配 system@'%' 两 条 记 录 按 照 前 面 介 绍 的 规 则, 如 果 是 在 localhost 本 地 执 行 登 录, 那 么 一 定 会 匹 配 为 system@'localhost' 这 个 用 户, 否 则 的 话, 则 会 是 system@'%' 这 个 用 户 了 再 给 一 个 例 子,user 表 中 有 以 下 两 条 记 录 : +----------------+----------+- Host User...
+----------------+----------+- www.5ienet.com... % jss... +----------------+----------+- 当 用 户 使 用 jss 用 户 并 且 从 www.5ienet.com 主 机 登 录 MySQL 数 据 库 时, 会 匹 配 第 一 条 记 录, 如 果 是 从 其 他 主 机 登 录 的 话 则 是 匹 配 第 二 条 记 录 实 际 上, 从 www.5ienet.com 主 机 登 录 MySQL 的 话, 是 否 指 定 用 户 根 本 就 没 有 区 别, 因 为 www.5ienet.com 已 经 非 常 明 确, 并 且 user 列 值 为 空 字 串, 也 就 代 表 着 只 要 是 从 www.5ienet.com 主 机 发 出 的 登 录 请 求, 不 管 指 定 的 用 户 是 什 么 ( 甚 至 可 以 是 user 表 中 不 存 在 的 用 户 ), 均 会 匹 配 为 这 条 记 录 4.GRANT 方 式 创 建 用 户 CREATE USER 只 是 创 建 用 户 的 高 速 路 之 一, 如 果 你 觉 得 这 条 道 路 实 在 太 过 平 坦, 路 边 风 景 太 过 平 淡, 行 程 太 过 平 常, 不 妨 在 抵 达 目 的 地 之 前, 拐 弯 开 上 GRANT 大 道, 饱 览 不 一 样 的 风 景 GRANT 命 令 并 非 本 小 节 重 点, 这 里 仅 简 要 描 述 一 下 其 语 句 中 与 用 户 相 关 的 部 分 : GRANT priv_clause TO user [IDENTIFIED BY [PASSWORD] 'password']... 与 创 建 用 户 相 关 的 语 法, 看 起 来 跟 CREATE USER 是 差 不 多 的 嘛, 事 实 上 当 然 不 是 差 不 多, 根 本 就 是 一 模 一 样 嘛, 下 面 举 个 例 子, 操 作 如 下 : (system@localhost) [(mysql)]> grant select on jssdb.* to jss_grant@192.168.30.203 identified by 'jss'; (system@localhost) [(mysql)]> select user,host,password from mysql.user where user ='jss_grant'; +-----------+----------------+-------------------------------------------+ user host password +-----------+----------------+-------------------------------------------+ jss_grant 192.168.30.203 *284578888014774CC4EF4C5C292F694CEDBB5457 +-----------+----------------+-------------------------------------------+ 1 row in set (0.00 sec) 上 述 语 句 在 实 现 了 前 面 第 3 个 例 子 ( 创 建 用 户 jss_ip) 的 功 能 外, 还 额 外 授 予 了 jss_grant 用 户 查 询 mysql.user 表 的 权 限 MySQL 的 开 发 团 队 靠 着 永 不 屈 服 永 不 放 弃 永 不 退 缩 永 不 言 败 的 奋 争 精 神, 用 智 慧 和 巧 妙 的 构 思 完 美 复 制 了 ORACLE GRANT 语 句 的 功 能, 这 是 全 世 界 默 默 无 闻 的 MySQL 开 发 人 员 长 期 以 来 内 生 品 格 的 自 然 流 露, 是 全 世 界 默 默 无 闻 的 MySQL 开 发 人 员 开 拓 前 进 的 不 竭 动 力, 这 就 是 传 说 中 的 瑞 典 梦 5. 另 类 方 式 创 建 用 户 如 果 说 觉 得 上 述 方 式 都 不 顺 手, 或 者, 大 脑 短 路 导 致 短 暂 忘 记 了 命 令 的 语 法, 那 也 没 关 系,mysql.user 表 还 记 得 吧, 直 接 向 该 字 典 表 中 插 入 记 录 ( 一 般 INSERT 语 法 想 忘 不 容 易 ), 也 是 靠 谱 的, 例 如 : (system@localhost) [(none)]> insert into mysql.user (host,user,password,ssl_cipher,x509_issuer, x509_subject) values ('192.168.30.203','jss_insert',password('jss'),'','',''); Query OK, 1 row affected (0.00 sec)
(system@localhost) [(none)]> select user,host,password from mysql.user where user ='jss_insert'; +------------+----------------+-------------------------------------------+ user host password +------------+----------------+-------------------------------------------+ jss_insert 192.168.30.203 *284578888014774CC4EF4C5C292F694CEDBB5457 +------------+----------------+-------------------------------------------+ 1 row in set (0.00 sec) 手 动 修 改 权 限 字 典 表 后, 需 要 执 行 FLUSH PRIVILEGES 语 句, 重 新 加 载 授 权 信 息 到 内 存 中, 否 则 手 动 修 改 的 权 限 不 会 生 效, 执 行 操 作 如 下 : (system@localhost) [none]> flush privileges; 接 下 来 可 以 尝 试 从 192.168.30.203 主 机, 分 别 使 用 jss_insert 和 jss_ip 登 录, 对 比 看 看 效 果, 不 仅 看 起 来 相 同, 实 际 表 现 也 是 一 模 一 样 这 点 跟 Oracle 数 据 库 就 截 然 不 同 了,Oracle 这 类 数 据 库 是 绝 对 不 建 议 用 户 修 改 数 据 字 典 表 的, 而 且 一 般 情 况 下 也 不 知 道 都 应 该 改 哪 些 地 方 ( 没 错, 完 全 可 能 不 止 一 处 需 要 修 改 ), 因 此 对 于 Oracle 数 据 库, 最 安 全 最 稳 妥 也 最 快 捷 的 方 式, 还 是 老 老 实 实 按 照 Oracle 提 供 的 命 令 进 行 操 作 而 MySQL 则 完 全 不 同, 官 方 不 仅 完 全 不 介 意 用 户 通 过 操 作 字 典 表 的 方 式 进 行 功 能 修 改 ( 想 想 也 是, 连 软 件 都 是 开 源 的, 在 这 种 地 方 设 什 么 障 碍 也 没 有 意 义 ), 甚 至 鼓 励 通 过 这 种 方 式 话 说 回 来, 截 止 到 MySQL5.6.12 版 本, 都 还 没 有 提 供 修 改 用 户 属 性 的 ALTER USER 的 语 法, 因 此 如 果 想 对 用 户 属 性 做 修 改, 直 接 UPDATE mysql.user 表 就 算 是 比 较 便 捷 的 方 式 了 当 然 啦,MySQL 中 的 用 户 其 实 也 没 什 么 属 性 可 供 修 改, 大 多 都 是 权 限, 唯 一 称 得 上 属 性 又 有 修 改 可 能 的, 就 是 用 户 的 密 码 信 息 了 前 面 介 绍 过 SET PASSWORD 语 句, 用 于 修 改 用 户 密 码 非 常 专 业, 但 并 不 是 唯 一 的 方 法, 在 MySQL 数 据 库 中, 我 们 可 以 使 用 更 加 直 接 的 方 式 实 际 上 之 前 就 这 么 干 过, 还 记 得 第 3 章 中 修 改 root 用 户 密 码 时 所 做 的 操 作 吗? 没 错, 用 户 的 信 息 保 存 在 mysql.user 字 典 表 中, 我 们 直 接 修 改 该 表 也 是 一 样 的 例 如, 直 接 修 改 字 典 表, 将 jss 用 户 的 密 码 变 更 为 123456, 执 行 操 作 如 下 : (system@localhost) [(none)]> update mysql.user set password=password('123456') where user='jss' and host='%'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 5.2.2 授 予 权 限 用 户 管 理 的 核 心 就 是 权 限 分 配,MySQL 数 据 库 中 授 予 权 限 有 专 用 命 令 GRANT, 它 不 仅 能 够 授 予 权 限, 甚 至 还 能 创 建 用 户 ( 前 面 小 节 中 演 示 过 ) 严 谨 些 描 述, 它 能 在 创 建 用 户 的 同 时 授 予 权 限, 看 起 来 授 权 操 作 倒 像 是 顺 带 的 功 能 一 样 GRANT 命 令 的 语 法 看 起 来 可 是 相 当 复 杂 的 呐 : GRANT priv_type [(column_list)]
[, priv_type [(column_list)]]... ON [object_type] priv_level TO user [IDENTIFIED BY [PASSWORD] 'password']... [REQUIRE {NONE ssl_option [[AND] ssl_option]...}] [WITH with_option...] 除 了 priv_type, 其 他 几 个 加 粗 的 子 项 详 细 语 法 如 下 : object_type: TABLE FUNCTION PROCEDURE priv_level: * *.* db_name.* db_name.tbl_name tbl_name db_name.routine_name ssl_option: SSL X509 CIPHER 'cipher' ISSUER 'issuer' SUBJECT 'subject' with_option: GRANT OPTION MAX_QUERIES_PER_HOUR count MAX_UPDATES_PER_HOUR count MAX_CONNECTIONS_PER_HOUR count MAX_USER_CONNECTIONS count 貌 似 漏 掉 了 priv_type 选 项, 放 心 我 没 忘, 最 重 要 的 priv_type 需 要 放 在 最 显 著 的 地 方 解 说 它 看 起 来 最 简 单, 但 可 选 项 也 最 多, 用 于 指 定 可 授 予 ( 或 收 回 ) 的 权 限 类 型, 对 此 官 方 文 档 中, 针 对 可 授 予 的 权 限, 专 门 列 了 个 表 罗 列 的 很 清 晰 ( 表 5-2) 表 5-2 MySQL 用 户 权 限 权 限 类 型 ALL [PRIVILEGES] ALTER ALTER ROUTINE CREATE CREATE ROUTINE CREATE TABLESPACE CREATE TEMPORARY TABLES 简 要 说 明 授 予 除 GRANT OPTION 外 的 所 有 权 限 允 许 执 行 ALTER TABLE 操 作 允 许 修 改 或 删 除 存 储 过 程 和 函 数 允 许 创 建 数 据 库 和 创 建 表 对 象 允 许 创 建 存 储 过 程 和 函 数 允 许 创 建 修 改 或 删 除 表 空 间 及 日 志 文 件 组 允 许 执 行 CREATE TEMPORARY TABLE 语 句 创 建 临 时 表
续 表 权 限 类 型 CREATE USER CREATE VIEW DELETE DROP EVENT EXECUTE FILE GRANT OPTION INDEX INSERT LOCK TABLES PROCESS PROXY REFERENCES RELOAD REPLICATION CLIENT REPLICATION SLAVE SELECT SHOW DATABASES SHOW VIEW SHUTDOWN SUPER TRIGGER UPDATE USAGE 简 要 说 明 允 许 执 行 CREATE USER DROP USER RENAME USER 和 REVOKE ALL PRIVILEGES 语 句 允 许 创 建 / 修 改 视 图 允 许 执 行 DELETE 语 句 允 许 删 除 数 据 库 / 表 或 视 图 允 许 使 用 Event 对 象 允 许 用 户 执 行 存 储 程 序 允 许 用 户 读 写 文 件 允 许 将 授 予 的 权 限 再 由 该 用 户 授 予 其 他 用 户 允 许 创 建 / 删 除 索 引 允 许 执 行 INSERT 语 句 允 许 对 拥 有 SELECT 权 限 的 表 对 象 执 行 LOCK TABLES 允 许 用 户 执 行 SHOW PROCESSLIST 命 令 查 看 当 前 所 有 连 接 允 许 使 用 PROXY 尚 未 应 用 允 许 执 行 FLUSH 操 作 允 许 用 户 连 接 复 制 环 境 中 的 Master/Slave 允 许 复 制 环 境 的 Slave 端 从 Master 端 读 取 数 据 允 许 执 行 SELECT 语 句 允 许 执 行 SHOW DATABASES 语 句 显 示 所 有 数 据 库 允 许 执 行 SHOW CREATE VIEW 查 看 视 图 定 义 允 许 通 过 mysqladmin 命 令 关 闭 数 据 库 允 许 执 行 管 理 操 作, 比 如 CHANGE MASTER TO KILL PURGE BINARY LOGS SET GLOBAL 等 语 句 允 许 创 建 或 删 除 触 发 器 允 许 执 行 UPDATE 操 作 意 指 没 有 权 限 (no privileges) 这 个 表 罗 列 了 所 有 可 授 予 用 户 的 权 限, 不 管 针 对 什 么 用 户, 授 予 哪 个 对 象, 授 予 什 么 粒 度 的 权 限, 都 是 从 表 5-2 中 的 关 键 字 中 选 择 以 上 几 段 加 一 块 基 本 上 就 是 GRANT 语 句 的 语 法, 看 起 来 呢 是 复 杂 了 一 点 点, 不 过 不 懂 也 没 关 系, 再 说 就 算 懂 了 也 不 一 定 记 得 住, 就 算 记 住 了 也 不 一 定 真 能 理 解 它 在 说 什 么
就 像 现 在 人 人 都 知 道 要 先 感 谢 国 家, 你 懂 的, 人 人 都 明 白 那 不 过 就 是 说 说 ( 不 过 海 外 各 种 二 代 及 二 代 亲 戚 们 说 这 话 时 应 该 是 真 心 的 ), 关 键 时 刻 得 动 真 格 的, 得 会 用 才 行, 三 思 争 取 后 面 多 弄 几 个 例 子, 让 大 家 伙 都 搞 明 白 这 个 事 儿 下 面 先 举 个 最 简 单 的 例 子 帮 助 大 家 理 解, 我 们 要 授 予 jss_grant@'192.168.30.203' 用 户 查 询 mysql.user 表 的 权 限, 执 行 语 句 如 下 : (system@localhost) [(none)]> grant select on mysql.user to jss_grant@'192.168.30.203'; 其 中 select 对 应 的 就 是 priv_type 中 的 权 限, mysql.user 对 应 priv_level 中 的 db_name.tbl_name, 这 是 一 个 最 简 单 的 示 例, 当 然 啦, 不 使 用 GRANT 语 句, 而 通 过 INSERT UPDATE 方 式 修 改 字 典 表 也 是 靠 谱 的! 话 说 MySQL 数 据 库 中 有 些 权 限 的 设 计 也 很 有 意 思, 值 得 说 道 几 句 首 先 是 关 于 CREATE/DROP 这 类 权 限, 这 是 个 很 有 意 思 的 设 定, 拿 CREATE 权 限 来 说, 如 果 一 个 用 户 拥 有 了 建 库 的 权 限, 那 么 它 也 一 定 能 创 建 表 ( 但 不 能 创 建 视 图 ), 此 处 的 粒 度 设 计 没 有 那 么 细,MySQL 数 据 库 并 没 有 将 建 库 和 建 表 设 计 成 两 种 权 限, 而 是 合 二 为 一 DROP 权 限 也 是 类 似 的 设 计, 不 过 与 CREATE 权 限 有 所 不 同 的 是,DROP 权 限 也 能 删 除 视 图 对 象 其 实 其 他 数 据 库 中 也 有 类 似 的 设 定, 比 如 Oracle 数 据 库 环 境, 某 个 用 户 拥 有 创 建 对 象 的 权 限 的 话, 那 么 它 就 一 定 拥 有 删 除 这 个 对 象 的 权 限 在 Oracle 看 来, 能 创 建 就 应 该 能 删 除, 这 两 者 是 一 体 的, 无 法 单 独 剥 离 就 我 个 人 看 来,Oracle 的 设 定 明 显 更 为 老 道, 而 且 符 合 逻 辑,MySQL 在 这 方 面 的 设 计 还 是 显 得 规 划 有 些 不 够 清 晰 其 次 关 于 ALL [PRIVILEGES] 和 GRANT OPTION 权 限, 这 是 两 种 比 较 特 殊 的 权 限, 甚 至 在 授 予 或 收 回 这 两 类 权 限 时 都 不 能 与 其 他 权 限 同 时 操 作, 并 且 这 两 个 权 限 并 不 像 它 们 名 字 显 示 的 那 样 是 全 部 的 权 限, 后 面 的 示 例 中 会 演 示 这 一 点 最 后 关 于 USAGE 权 限, 按 照 表 5-2 的 描 述 中 所 示, 这 个 权 限 的 功 能 就 是 没 有 权 限, 但 其 实 它 不 是 完 全 没 有 权 限, 至 少 它 还 有 一 项 权 限, 就 是 登 录 权 限 对 于 使 用 CREATE USER 语 句 创 建 的 用 户, 该 用 户 默 认 就 会 拥 有 USAGE 权 限, 但 是, 又 的 确 像 描 述 中 所 说 的 那 样, 这 个 用 户 除 了 能 够 登 录 数 据 库, 别 的 什 么 也 做 不 了, 因 此 就 像 是 没 有 权 限 另 外, 还 得 再 简 要 说 一 下 with_option 的 几 个 选 项 : GRANT OPTION: 允 许 用 户 再 将 该 权 限 授 予 其 他 用 户 MAX_QUERIES_PER_HOUR: 允 许 用 户 每 小 时 执 行 的 查 询 语 句 数 量 MAX_UPDATES_PER_HOUR: 允 许 用 户 每 小 时 执 行 的 更 新 语 句 数 量 MAX_CONNECTIONS_PER_HOUR: 允 许 用 户 每 小 时 连 接 的 次 数 MAX_USER_CONNECTIONS: 允 许 用 户 同 时 连 接 服 务 器 的 数 量 这 块 的 内 容 一 看 就 是 给 用 户 设 限 制 用 的, 我 个 人 认 为 意 义 不 大, 不 是 说 没 有 这 类 需 求, 而 是 这 些 选 项 的 粒 度 仍 然 不 够 细 致, 不 易 碰 到 适 合 的 应 用 场 景 不 过 简 单 了 解 一 下 也 是 有 必 要 的, 万 一 哪 天 对 某 用 户 看 着 不 爽,DBAer 心 里 应 该 明 白, 还 是 有 法 子 限 制 该 用 户 能 够
使 用 的 资 源 的 其 他 部 分 就 先 不 多 说 了, 何 况 这 个 事 儿 也 不 能 说 得 太 细, 主 要 是 太 细 的 东 西 三 思 也 不 懂, 不 懂 装 懂 这 个 事 儿 俺 脸 皮 虽 然 已 经 很 厚, 但 做 这 类 事 儿 的 时 候 表 情 总 是 不 够 自 然, 不 过 请 同 学 们 放 心, 俺 一 定 会 继 续 努 力, 争 取 早 日 复 制 粘 贴 那 谁 的 成 功, 用 俺 的 真 诚 蒙 到 别 人, 蒙 到 所 有 的 人 5.2.3 查 看 和 收 回 用 户 权 限 不 管 是 授 予 还 是 收 回 用 户 的 权 限, 通 常 首 先 需 要 知 道 用 户 当 前 都 拥 有 什 么 权 限 查 询 用 户 权 限 可 以 使 用 SHOW GRANTS 语 句,SHOW GRANTS 的 语 法 比 较 简 单, 就 一 行 : SHOW GRANTS [FOR user] 其 中 FOR user 还 是 个 可 选 项, 用 于 指 定 要 查 询 的 目 标 用 户, 如 果 不 指 定 的 话, 则 默 认 显 示 当 前 用 户 拥 有 的 权 限, 效 果 等 同 于 SHOW GRANTS FOR CURRENT_USER() 如 果 之 前 从 未 用 过, 那 么 SHOW GRANTS 语 句 显 示 的 结 果 可 能 会 出 乎 意 料, 它 返 回 的 结 果 并 不 是 某 个 权 限 类 型 的 关 键 字, 而 是 授 权 语 句 例 如, 查 看 用 户 jss_grant@192.168.30.203 都 拥 有 哪 些 权 限, 执 行 语 句 如 下 : (system@localhost) [(none)]> show grants for jss_grant@192.168.30.203; +-------------------------------------------------------------------------------------------+ Grants for jss_grant@192.168.30.203 +-------------------------------------------------------------------------------------------+ GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774 CC4EF4C5C292F694CEDBB5457' GRANT SELECT ON 'jssdb'.* TO 'jss_grant'@'192.168.30.203' GRANT SELECT ON 'mysql'. 'user' TO 'jss_grant'@'192.168.30.203' +-------------------------------------------------------------------------------------------+ 3 rows in set (0.00 sec) 从 上 述 返 回 的 结 果 可 以 看 到, 用 户 jss_grant@192.168.30.203 拥 有 3 项 权 限 : 查 询 mysql.user 表 查 询 jssdb 数 据 库 下 所 有 对 象 的 权 限 以 及 登 录 MySQL 数 据 库 的 权 限 要 我 说,MySQL 数 据 库 SHOW GRANTS 语 法 最 喜 人 之 处 在 于, 创 建 用 户 和 授 权 语 法 都 列 出 来 了 尽 管 前 面 我 已 经 无 数 次 提 到 过, 直 接 查 询 mysql 库 中 的 数 据 字 典 表 来 修 改 或 查 看 用 户 的 权 限 信 息, 但 我 觉 着 如 果 是 要 查 看 某 个 用 户 的 权 限, 使 用 SHOW GRANTS 语 句 才 是 最 好 的 方 式, 功 能 超 强 而 且 易 用 要 收 回 用 户 权 限, 与 之 对 应 的 命 令 是 REVOKE, 它 的 语 法 从 定 义 上 分 为 两 种 : REVOKE priv_type [(column_list)] [, priv_type [(column_list)]]... ON [object_type] priv_level FROM user [, user]... REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user]... 前 者 用 来 处 理 指 定 的 权 限, 有 很 多 选 项, 这 些 选 项 的 定 义 与 GRANT 中 同 名 选 项 定 义 一 模 一 样, 这 里 不 再 赘 述 后 者 功 能 较 为 独 立, 可 以 理 解 成 专 用 于 清 除 用 户 权 限
我 们 先 来 尝 试 收 回 jss_grant@'192.168.30.203' 用 户, 拥 有 的 mysql.user 表 对 象 的 SELECT 权 限, 执 行 REVOKE 命 令 如 下 : (system@localhost) [(none)]> revoke select on mysql.user from jss_grant@192.168.30.203; (system@localhost) [(none)]> show grants for jss_grant@192.168.30.203; +------------------------------------------------------------------------------------------+ Grants for jss_grant@192.168.30.203 +------------------------------------------------------------------------------------------+ GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774 CC4EF4C5C292F694CEDBB5457' GRANT SELECT ON `jssdb`.* TO 'jss_grant'@'192.168.30.203' +------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) 收 回 某 个 普 通 的 指 定 权 限 立 竿 见 影 注 意, 我 说 的 是 普 通 权 限 有 哪 些 权 限 不 普 通 呢? 如 果 此 刻 你 的 内 心 浮 现 出 这 个 问 题, 说 明 看 书 不 认 真 啊! 在 前 面 介 绍 GRANT 语 句 时 就 曾 提 到 过 的, 比 如 说 USAGE 权 限, 这 个 权 限 用 户 一 经 创 建 就 会 拥 有, 并 且 无 法 通 过 REVOKE 语 句 收 回 你 要 不 相 信 哪, 咱 们 来 看 一 看 : (system@localhost) [(none)]> revoke usage on *.* from 'jss_grant'@'192.168.30.203'; 操 作 提 示 成 功, 但 这 是 个 假 象, 可 以 通 过 查 看 jss_grant 用 户 拥 有 的 权 限 来 验 证 : (system@localhost) [(none)]> show grants for jss_grant@192.168.30.203; +-------------------------------------------------------------------------------------------+ Grants for jss_grant@192.168.30.203 +-------------------------------------------------------------------------------------------+ GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774 CC4EF4C5C292F694CEDBB5457' GRANT SELECT ON `jssdb`.* TO 'jss_grant'@'192.168.30.203' +-------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) 毫 无 变 化 前 面 revoke 之 所 以 没 有 报 错, 也 跟 MySQL 在 语 句 执 行 上 的 设 定 有 关 系 比 方 说, 您 可 以 尝 试 revoke 任 意 权 限 from user, 它 都 不 会 报 错 的 之 前 曾 提 到 过,MySQL 的 返 回 就 是 这 个 德 性 :Query OK, 0 rows affected 此 外 前 面 三 思 还 提 到 过 特 殊 的 ALL PRIVILEGES, 这 个 权 限 也 不 像 字 面 意 义 那 么 简 单, 所 谓 所 有 权 限 指 的 不 是 所 有 哟 你 要 不 相 信 呀, 咱 们 再 来 看 一 看, 对 jss_grant@ '192.168.30.203' 用 户 执 行 REVOKE ALL PRIVILEGES: (system@localhost) [(none)]> revoke all privileges on *.* from jss_grant@'192.168.30.203'; 提 示 信 息 总 是 这 样, 我 们 能 猜 得 到 开 头, 不 过 能 猜 得 对 结 局 不? 还 是 实 际 验 证 一 下 吧 : (system@localhost) [(none)]> show grants for jss_grant@192.168.30.203; +----------------------------------------------------------------------------------------------+ Grants for jss_grant@192.168.30.203 +----------------------------------------------------------------------------------------------+
GRANT USAGE ON *.* TO 'jss_grant'@'192.168.10.203' IDENTIFIED BY PASSWORD '*284578888014774CC4EF4C5C292F694CEDBB5457' GRANT SELECT ON `jssdb`.* TO 'jss_grant'@'192.168.30.203' +----------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) 又 是 毫 无 作 用 那 个 特 殊 的 USAGE 权 限 就 不 说 了, 可 是 ALL PRIVILEGES 居 然 连 小 小 的 普 通 的 SELECT 权 限 都 没 能 收 回, 这 还 称 得 上 ALL 吗? 呃, 这 个, 称 得 上, 它 只 是 功 能 的 设 计 并 不 像 我 们 想 象 的 那 样 而 已 这 几 个 知 识 点 是 MySQL 数 据 库 的 权 限 体 系 设 计 上 的 细 节, 如 不 注 意 就 有 可 能 错 误 理 解 前 后 两 个 操 作 尽 管 看 起 来 结 果 相 同, 但 结 论 是 完 全 不 同 的, 前 者 是 由 于 USAGE 在 MySQL 权 限 体 系 中 对 于 用 户 的 特 殊 意 义, 后 者 是 由 于 系 统 设 计 层 的 因 素 MySQL 数 据 库 中 的 权 限, 操 作 时 授 予 和 收 回 的 权 限 级 别 (priv_level) 必 须 对 应, 否 则 无 法 成 功 回 收 就 上 面 这 个 例 子 中, 授 予 jss_grant@'192.168.30.203' 用 户 SELECT 权 限 时, 是 基 于 jssdb 这 样 一 个 库 级 授 予 的, 那 么 回 收 时, 也 必 须 明 确 指 定 是 基 于 库 级 回 收, 如 果 指 定 all on *.*, 则 无 法 收 回 jssdb.* 的 权 限, 这 也 正 是 MySQL 数 据 库 权 限 粒 度 分 级 的 特 点 因 此, 如 果 要 让 REVOKE ALL PRIVILEGES 语 句 正 确 有 效 地 执 行, 就 应 该 明 确 指 定 on jssdb.*, 例 如 : (system@localhost) [(none)]> revoke all privileges on jssdb.* from jss_grant@'192.168.30.203'; (system@localhost) [(none)]> show grants for jss_grant@192.168.30.203; +----------------------------------------------------------------------------------------------+ Grants for jss_grant@192.168.30.203 +----------------------------------------------------------------------------------------------+ GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774CC4EF4C5C292F694CEDBB5457' +----------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) 这 下 终 于 成 功 将 权 限 收 回 了 三 思 有 过 多 年 的 Oracle 数 据 库 使 用 经 验, 在 尝 试 使 用 和 学 习 MySQL 数 据 库 期 间 感 触 很 深,MySQL 数 据 库 设 计 的 确 实 很 有 特 点, 我 想 对 于 初 学 者, 只 要 小 脑 袋 瓜 没 有 停 止 思 考, 一 定 会 持 续 不 断 冒 出 各 种 各 样 的 问 题 对 于 用 户 的 权 限 回 收, 经 过 前 面 一 些 演 示, 想 必 朋 友 们 又 会 有 新 的 疑 问 : 若 用 户 拥 有 各 种 不 同 级 别 不 同 粒 度 不 同 的 权 限, 回 收 时 难 道 也 必 须 一 一 指 定 回 收 吗? 这 岂 不 是 太 过 繁 琐 了 关 于 这 一 点, 我 可 以 负 责 任 地 说, 把 心 踏 踏 实 实 搁 肚 子 里 头 吧,MySQL 数 据 库 就 跟 繁 琐 俩 字 不 沾 边, 作 为 一 款 开 源 的 轻 量 级 数 据 库,MySQL 就 没 有 什 么 复 杂 的 特 性, 自 然 也 不 会 有 繁 琐 的 操 作 对 于 前 面 这 个 疑 问, 如 果 确 定 要 干 净 利 索 地 清 除 某 个 用 户 的 所 有 权 限, 并 且 还 要 保 留 这 个 用 户 ( 这 是 什 么 变 态 需 求 ), 那 么,REVOKE 语 句 的 第 二 种 语 法 派 上 用 场 了 : REVOKE ALL PRIVILEGES, GRANT OPTION FROM user 这 是 个 固 定 语 法, 功 能 正 是 用 于 收 回 用 户 的 所 有 权 限, 不 管 授 予 用 户 的 是 什 么 权 限 级
别 什 么 对 象 的 什 么 权 限, 一 条 语 句 执 行 下 去, 直 接 将 用 户 恢 复 至 裸 身 (USAGE) 状 态 当 前,jss_grant@'192.168.30.203' 用 户 有 各 类 权 限 如 下 : (system@localhost) [(none)]> show grants for jss_grant@'192.168.30.203'; +----------------------------------------------------------------------------------------------+ Grants for jss_grant@192.168.30.203 +----------------------------------------------------------------------------------------------+ GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774 CC4EF4C5C292F694CEDBB5457' GRANT UPDATE, DELETE ON `jssdb`.* TO 'jss_grant'@'192.168.30.203' GRANT ALTER ON `jssdb_mc`.* TO 'jss_grant'@'192.168.30.203' GRANT SELECT ON `mysql`.`user` TO 'jss_grant'@'192.168.30.203' +----------------------------------------------------------------------------------------------+ 4 rows in set (0.00 sec) 怎 么 一 次 性 收 回 所 有 权 限 呢? 执 行 REVOKE 语 句 如 下 : (system@localhost) [(none)]> revoke all,grant option from jss_grant@'192.168.30.203'; (system@localhost) [(none)]> show grants for jss_grant@192.168.30.203; +----------------------------------------------------------------------------------------------+ Grants for jss_grant@192.168.30.203 +----------------------------------------------------------------------------------------------+ GRANT USAGE ON *.* TO 'jss_grant'@'192.168.30.203' IDENTIFIED BY PASSWORD '*284578888014774 CC4EF4C5C292F694CEDBB5457' +----------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) 你 看, 你 看, 用 户 的 权 限 悄 悄 地 在 改 变 5.2.4 删 除 用 户 我 想 不 出 一 个 仅 拥 有 USAGE 权 限 的 用 户 存 在 的 意 义, 干 脆, 删 了 它 吧! 怎 么, 您 担 心 会 丢 失 数 据 影 响 系 统 稳 定, 放 心 吧! 一 个 失 势 的 人 对 组 织 是 没 什 么 危 险 的, 只 要 权 利 被 收 回, 它 就 立 刻 什 么 都 不 是 很 多 人 之 所 以 担 心 删 用 户 会 丢 数 据, 主 要 是 受 其 他 数 据 库 产 品 的 影 响, 比 如 说 Oracle 中 删 除 用 户 ( 或 其 他 对 象, 比 如 表 空 间 ), 如 果 该 用 户 下 有 很 多 的 对 象, 那 么 删 除 用 户 的 同 时 也 会 把 这 些 对 象 及 关 联 的 数 据 统 统 删 除, 尽 管 Oracle 会 人 性 化 地 提 醒 你 删 除 的 用 户 下 仍 然 存 在 数 据, 但 如 果 强 制 级 联 删 除 ( 附 加 CASCADE 选 项 ), 那 么 该 删 就 还 是 删 了 MySQL 的 删 除 用 户 语 法 中 就 不 存 在 CASCADE 的 选 项, 为 什 么 不 存 在 呢? 并 不 是 MySQL 对 数 据 的 保 护 不 如 Oracle 那 么 上 心, 而 是 由 最 重 要 的 一 条 与 Oracle 不 同 的 机 制 决 定 MySQL 数 据 库 中 的 对 象 保 存 并 不 是 依 赖 于 用 户, 而 是 依 赖 于 库 (database), 用 户 被 删 除 没 有 任 何 关 系, 对 象 仍 在, 好 好 地 保 存 在 存 储 它 的 数 据 库 中 因 此,MySQL 数 据 库 中 的 用 户 删 了 就 删 了, 如 果 外 部 应 用 不 使 用 该 用 户 的 话, 那 么
我 们 可 以 认 为 该 用 户 被 删 除 无 影 响 即 使 发 现 真 的 删 错 了, 想 给 它 恢 复 身 份 的 话 也 很 简 单, 这 不 就 是 一 句 话 的 事 儿 嘛, 只 要 重 新 向 mysql.user 表 插 入 记 录 ( 注 册 建 档 ), 并 授 予 所 需 权 限 即 可 ( 授 予 官 阶 ), 至 于 底 层 数 据 的 意 见 那 是 完 全 可 以 忽 视 的 看 我 说 的 这 么 笃 定, 下 面 就 实 际 删 个 试 试 吧!MySQL 中 删 除 用 户 的 语 法 非 常 简 单 : DROP USER user [, user]... 从 语 法 上 大 家 想 必 也 都 看 出 来 了, 可 以 一 次 性 删 除 多 个 用 户, 这 里 三 思 就 准 备 一 步 删 除 之 前 创 建 的 jss_grant jss_insert 和 jss_ip 几 个 用 户, 执 行 DROP USER 命 令 如 下 : (system@localhost) [(none)]> drop user jss_grant@192.168.30.203, jss_insert@192.168.30.203, jss_ip@192.168.30.203; 需 要 说 明 的 一 点 是,DROP USER 不 会 自 动 中 止 已 连 接 的 用 户 会 话, 也 就 是 说 被 删 的 用 户 如 果 在 删 前 已 经 连 接 上 了 服 务 器, 并 且 连 接 尚 未 中 断, 那 它 此 时 还 能 继 续 执 行 一 定 的 操 作, 只 是 它 的 身 份 已 经 变 成 了 黑 户 5.3 权 限 级 别 总 的 来 说,MySQL 数 据 库 的 权 限 从 大 的 粒 度 上 可 以 分 成 5 类 : 全 局 数 据 库 表 列 程 序 通 过 对 这 5 个 大 类 权 限 的 细 分, 可 以 精 确 地 为 某 个 用 户 分 配 从 某 台 机 器 连 接 进 来 访 问 某 个 数 据 库 下 某 个 表 的 某 个 列 的 某 部 分 记 录 权 限 授 权 主 要 是 通 过 GRANT 命 令 ( 或 手 动 向 字 典 表 中 插 入 或 修 改 记 录 ), 对 应 的 权 限 关 键 字, 就 是 5.2 节 中 所 列 的 priv_type, 相 对 于 Oracle 数 据 库 来 说, 我 个 人 认 为,MySQL 数 据 库 中 权 限 设 定 真 简 单 注 意, 简 单 不 是 一 个 贬 义 词, 三 思 曾 经 无 数 次 在 无 数 个 场 合 强 调 过 这 样 一 种 观 点 : 简 单 意 味 着 灵 活, 而 灵 活 在 有 心 人 的 手 上 能 实 现 的 功 能 非 常 之 强 大 本 章 尽 可 能 多 的 通 过 示 例, 帮 助 大 家 理 解 GRANT 语 句 的 用 法, 当 然, 最 重 要 的 是 理 解 MySQL 数 据 库 的 权 限 体 系, 考 虑 到 MySQL 中 的 各 级 权 限 主 要 基 于 若 干 个 字 典 表, 因 此 本 段 介 绍 时 会 将 这 几 个 字 典 表 的 结 构 列 为 重 要 参 照 提 示 user/db/host 几 个 字 典 表 中,host 列 的 值 对 大 小 写 不 敏 感 User Password Db 和 Table_name 几 个 列 值 对 大 小 写 敏 感 Column_name 列 值 对 大 小 写 不 敏 感 5.3.1 全 局 全 局 这 个 词 儿 一 听 就 知 道 层 次 很 高, 宏 观 的 事 物 都 很 重 要, 你 看 播 音 员 每 当 提 到 宏 观 ( 经 济 数 据 ) 都 是 一 脸 的 肃 穆, 连 那 个 号 称 60 年 没 出 过 一 条 假 新 闻 的 著 名 报 纸, 发 表 宏 观 经 济 数 据 时 都 兴 奋 得 跟 打 了 鸡 血 似 的, 不 是 喊 保 8 就 是 喊 超 9, 虽 然 我 怎 么 也 闹 不 明 白 8
和 9 到 底 是 什 么 情 况 具 体 到 MySQL 这 样 一 款 小 软 件, 全 局 这 个 级 别 也 差 不 到 哪 儿 去, 我 就 说 一 条, 与 全 局 相 关 的 权 限 信 息 记 在 mysql.user 表 中 这 下 大 家 知 道 厉 害 了 吧,mysql.user 表 对 象 里 是 等 闲 数 据 能 待 的 地 方 吗? 前 面 提 到 过, 这 个 表 管 登 录, 控 制 用 户 能 不 能 连 接 这 样 一 等 一 的 最 重 要 的 事 情, 闲 杂 记 录 能 保 存 在 这 里 吗? 但 是 我 们 也 要 注 意 了, 这 个 全 局 权 限 可 不 一 定 就 能 拥 有 所 有 的 权 限, 它 具 体 指 的 是 能 够 拥 有 该 MySQL 服 务 器 所 有 数 据 库 的 [ 所 有 ] 对 象 的 [ 所 有 ] 权 限 ( 注 :[] 表 示 可 选 ) 下 面 新 创 建 一 个 用 户, 并 授 予 它 CREATE 权 限, 代 码 如 下 : (system@localhost) [(none)]> grant create on *.* to jss_global; system@localhost) [(none)]> select * from mysql.user where user='jss_global'\g *************************** 1. row *************************** Host: % User: jss_global Password: Select_priv: N Insert_priv: N Update_priv: N Delete_priv: N Create_priv: Y Drop_priv: N Reload_priv: N......... 1 row in set (0.00 sec) 查 看 返 回 的 mysql.user 表 中 记 录 的 信 息, 所 有 与 权 限 相 关 列 的 列 值 多 为 'N', 表 示 没 有 权 限, 只 有 被 授 予 了 全 局 操 作 权 限,mysql.user 表 中 权 限 对 应 列 值 才 是 'Y', 这 种 情 况 下, 该 用 户 就 拥 有 在 所 连 接 的 MySQL 服 务 器 下 所 有 数 据 库 中 执 行 相 应 操 作 的 权 限 以 前 面 创 建 的 jss_global 用 户 为 例, 授 予 了 CREATE 权 限 之 后, 该 用 户 即 可 轻 松 查 看 ( 没 错, 不 仅 能 创 建, 还 能 查 看 ) 当 前 连 接 的 MySQL 数 据 库 中 创 建 的 所 有 数 据 库, 并 能 够 在 任 意 数 据 库 中 创 建 表 对 象 (information_schema 库 除 外, 该 库 具 有 一 定 特 殊 性, 后 面 章 节 详 述 ) 找 台 客 户 端, 以 jss_global 用 户 登 录, 由 于 创 建 时 没 有 指 定 主 机 和 密 码 信 息, 因 此 可 以 从 任 意 主 机 并 且 无 需 输 入 任 何 密 码 登 录 : [mysql@mysqldb02 ~]$ mysql -ujss_global -h 192.168.30.243 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 17 Server version: 5.6.12-log JSS for mysqltest...... (jss_global@192.168.30.243) [(none)]>
执 行 SHOW DATABASES 命 令, 可 以 查 看 当 前 存 在 的 所 有 数 据 库 : (jss_global@192.168.30.243) [(none)]> show databases; +--------------------+ Database +--------------------+ information_schema jssdb jssdb_mc mysql performance_schema +--------------------+ 5 rows in set (0.00 sec) 创 建 表 对 象, 也 没 有 问 题, 如 在 jssdb 库 中 创 建 一 个 名 为 test1 的 表 对 象 : (jss_global@192.168.30.243) [(none)]> use jssdb; Database changed (jss_global@192.168.30.243) [(jssdb)]> create table test1 (vl varchar(20)); 创 建 成 功, 大 家 可 以 通 过 SHOW TABLES 命 令 或 DESC 命 令 查 看 验 证, 这 里 不 演 示 了 MySQL 数 据 库 中 权 限 的 设 计 自 有 其 逻 辑, 有 些 设 定 符 合 人 们 ( 谨 代 表 我 个 人 ) 的 常 规 思 维, 有 些 则 跟 我 们 下 意 识 的 认 知 有 较 大 差 距 就 拿 刚 刚 演 示 的 这 个 CREATE 权 限 来 说, 当 用 户 拥 有 全 局 的 CREATE 权 限, 那 么 它 同 时 也 级 联 拥 有 了 查 看 所 有 数 据 库 (SHOW DATABASES) 和 数 据 库 下 所 有 对 象 的 权 限, 能 建 就 能 看, 这 点 容 易 理 解 ; 但 是, 明 确 授 予 的 CREATE 权 限, 又 确 实 只 拥 有 创 建 的 权 限, 想 删 除 对 象 是 不 行 的, 哪 怕 这 个 对 象 就 是 它 刚 刚 创 建 的 : (jss_global@192.168.30.243) [jssdb]> drop table test1; ERROR 1142 (42000): DROP command denied to user 'jss_global'@'192.168.30.203' for table 'test1' 修 改 也 不 行 : (jss_global@192.168.30.243) [jssdb]> alter table test1 add (vl varchar(20)); ERROR 1142 (42000): ALTER command denied to user 'jss_global'@'192.168.30.203' for table 'test1' 甚 至 连 查 询 都 不 行 : (jss_global@192.168.30.243) [jssdb]> select * from test1; ERROR 1142 (42000): SELECT command denied to user 'jss_global'@'192.168.30.203' for table 'test1' 现 在 您 明 白 了 吧, 他 授 予 的 仅 仅 只 是 CREATE 权 限, 想 删 除 是 不 行 的, 连 查 看 都 是 肯 定 不 行 的 对 对, 即 使 要 删 除 的 对 象 是 自 己 刚 刚 创 建 的 也 不 行 不 不, 多 贵 的 计 算 机 都 不 行 全 局 这 么 重 要 的 粒 度, 能 够 在 这 一 级 授 予 的 权 限 自 然 不 少, 在 5.2.2 小 节 中 提 到 的 权 限 大 部 分 都 可 以 在 全 局 级 授 予, 与 MySQL 服 务 管 理 相 关 的 权 限 则 全 部 是 在 全 局 级 进 行 设 置 表 5-3 罗 列 了 可 在 全 局 粒 度 授 予 的 权 限, 以 及 该 权 限 与 mysql.user 字 典 表 列 的 对 应 关 系
user 字 典 表 列 名 select_priv insert_priv update_priv delete_priv create_priv drop_priv reload_priv shutdown_priv process_priv file_priv grant_priv references_priv index_priv alter_priv show_db_priv super_priv create_tmp_table_priv lock_tables_priv execute_priv repl_slave_priv repl_client_priv create_view_priv show_view_priv create_routine_priv alter_routine_priv create_user_priv event_priv trigger_priv create_tablespace_priv 表 5-3 全 局 权 限 列 表 对 应 权 限 名 SELECT INSERT UPDATE DELETE CREATE DROP RELOAD SHUTDOWN PROCESS FILE GRANT OPTION REFERENCES INDEX ALTER SHOW DATABASES SUPER CREATE TEMPORARY TABLES LOCK TABLES EXECUTE REPLICATION SLAVE REPLICATION CLIENT CREATE VIEW SHOW VIEW CREATE ROUTINE ALTER ROUTINE CREATE USER EVENT TRIGGER CREATE TABLESPACE
提 示 默 认 情 况 下, 使 用 CREATE USER 创 建 的 用 户, 能 够 登 录 MySQL 数 据 库, 并 且 还 具 有 操 作 test 库 中 对 象 的 权 限, 这 是 MySQL 数 据 库 的 默 认 设 定, 关 于 test 数 据 库 的 权 限 问 题, 将 在 后 面 章 节 中 专 门 描 述 5.3.2 数 据 库 数 据 库 级 别 的 权 限, 主 要 用 于 控 制 账 户 ('user'@'host') 操 作 某 个 数 据 库 的 权 限, 在 这 一 粒 度 对 用 户 做 了 授 权 后, 用 户 就 拥 有 了 该 数 据 库 下 [ 所 有 ] 对 象 的 [ 所 有 ] 权 限 数 据 库 级 别 的 权 限 信 息 记 录 在 mysql.db 表 在 介 绍 mysql.db 表 之 前, 三 思 想 先 特 别 提 一 下 mysql.host 表, 这 个 表 也 与 数 据 库 粒 度 的 权 限 有 关 联, 它 的 功 能 相 对 奇 特, 是 用 于 控 制 某 些 主 机 (host) 是 否 拥 有 操 作 某 个 数 据 库 的 权 限, 在 可 设 置 的 权 限 方 面 跟 mysql.db 几 乎 一 模 一 样 mysql.host 表 在 MySQL 5.5 及 之 前 版 本 中 的 处 境 很 特 别, 默 认 情 况 下 GRANT/REVOKE 语 句 并 不 触 发 对 该 表 数 据 的 读 写, 因 此 多 数 情 况 下 该 表 都 没 啥 用, 极 易 被 忽 略 不 过 在 应 对 某 些 特 定 场 景 下,DBA 可 以 手 动 操 作 (insert update delete) 该 表 来 实 现 某 些 特 殊 的 需 求 比 如 说 只 希 望 某 些 主 机 拥 有 操 作 某 个 数 据 库 的 权 限 时,mysql.user 完 全 派 不 上 用 场 ( 它 是 针 对 全 局 的 嘛, 管 不 到 db 这 么 细 的 粒 度 ), 那 么 使 用 mysql.host 就 可 以 轻 松 实 现, 因 为 该 表 对 权 限 的 验 证 正 是 使 用 host 这 个 维 度 当 然 啦, 这 个 需 求 使 用 mysql.db 表 也 可 以 实 现,mysql.db 表 是 通 过 user+host 两 个 维 度 来 验 证 权 限, 比 mysql.host 多 了 一 个 维 度, 不 过 由 于 MySQL 数 据 库 的 权 限 字 典 表 能 够 支 持 通 配 符, 并 且 user 列 可 以 为 空 ( 代 表 所 有 用 户 ), 通 过 灵 活 设 置 也 可 以 实 现 mysql.host 表 的 功 能 我 想 也 正 是 基 于 此, 从 5.6 版 本 开 始,mysql.host 表 已 被 明 确 废 弃 不 过 如 果 您 在 使 用 之 前 版 本 的 数 据 库, 恰 好 场 景 适 当, 倒 是 仍 可 以 用 用 mysql.host 表 还 是 回 到 mysql.db 表 吧, 功 能 前 头 已 经 说 过 了, 不 过 出 于 加 深 印 象 的 目 的, 我 再 重 复 说 一 遍 大 家 没 什 么 意 见 吧, 有 意 见 也 不 要 紧, 我 的 邮 箱 地 址 网 上 都 写 着 哪, 有 啥 抱 怨 的 话 尽 管 发,Gmail 邮 箱, 空 间 有 好 个 G 哪 我 个 人 感 觉 将 数 据 库 级 权 限 与 全 局 级 权 限 对 比 起 来 更 好 理 解, 全 局 级 权 限 大 家 都 知 道 了 吧, 用 来 控 制 用 户 操 作 所 有 数 据 库 的 权 限 ( 以 及 管 理 MySQL 服 务 的 权 限 ), 数 据 都 是 保 存 在 mysql.user 字 典 表 中 若 只 希 望 授 予 用 户 操 作 某 个 数 据 库 的 权 限, 该 怎 么 办 呢? 那 就 该 mysql.db 出 马 啦! 你 要 问 mysql.user 和 mysql.db 差 在 哪 儿, 对 比 一 下 两 个 字 典 表 的 表 结 构 您 就 明 白 啦 ( 表 5-4)
表 5-4 全 局 和 库 级 权 限 对 应 表 Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv References_priv Index_priv Alter_priv mysql.user 表 Host User Db Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv mysql.db 表 Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv Shutdown_priv Process_priv......... Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv 你 看,mysql.db 表 中 有 的 列, 在 mysql.user 中 几 乎 全 都 有, 而 mysql.user 中 有 的 列 则 有 一 堆 mysql.db 表 中 都 不 存 在 呀 看 看 前 面 章 节 中 介 绍 的 权 限 说 明, 多 出 的 列 正 是 MySQL 服 务 级 的 管 理 权 限, 说 mysql.db 是 mysql.user 表 的 子 集 都 不 为 过 mysql.db 与 mysql.user 相 比 多 出 的 Db 列, 不 正 是 用 来 指 定 要 管 理 的 目 标 数 据 库 嘛!
授 予 用 户 某 个 数 据 库 的 管 理 权 限, 执 行 GRANT 语 句 时, 相 比 全 局 就 得 缩 小 授 权 范 围, 把 全 局 时 指 定 的 *.* 改 成 dbname.* 就 行 啦! 例 如, 创 建 jss_database 用 户, 并 授 予 jssdb 库 下 创 建 对 象 的 权 限, 执 行 命 令 如 下 : (system@localhost) [(none)]> grant create on jssdb.* to jss_db; 创 建 成 功, 查 看 jss_db 用 户 在 各 字 典 表 的 记 录 明 细, 以 便 我 们 能 够 更 清 晰 地 理 解 权 限 字 典 表 在 用 户 权 限 环 境 所 起 到 的 作 用 先 来 看 看 刚 刚 创 建 的 用 户, 在 mysql.user 全 局 权 限 表 中 的 信 息 : (system@localhost) [(none)]> select * from mysql.user where user='jss_database'\g *************************** 1. row *************************** Host: % User: jss_database Password: Select_priv: N Insert_priv: N Update_priv: N Delete_priv: N Create_priv: N Drop_priv: N Reload_priv: N Shutdown_priv: N...... 操 作 类 权 限 都 是 N( 相 当 于 仅 拥 有 USAGE 权 限 ), 这 就 对 了, 允 许 该 用 户 登 录 MySQL 数 据 库 那 么 操 作 jssdb 数 据 库 的 权 限 写 在 哪 了 呢? 再 看 看 mysql.db 库 级 权 限 字 典 表 吧 : (system@localhost) [(none)]> select * from mysql.db where user='jss_db'\g *************************** 1. row *************************** Host: % Db: jssdb User: jss_db Select_priv: N Insert_priv: N Update_priv: N Delete_priv: N Create_priv: Y Drop_priv: N Grant_priv: N References_priv: N Index_priv: N Alter_priv: N Create_tmp_table_priv: N Lock_tables_priv: N Create_view_priv: N Show_view_priv: N Create_routine_priv: N Alter_routine_priv: N
Execute_priv: N Event_priv: N Trigger_priv: N 1 row in set (0.00 sec) 这 下 就 比 较 清 晰 了,Db 表 显 示 了 可 操 作 的 库 名,Create_priv 列 值 显 示 Y, 表 示 这 个 用 户 拥 有 指 定 库 中 对 象 的 创 建 权 限 下 面 再 通 过 该 用 户 连 接 到 MySQL 数 据 库 中 看 一 下 吧! 使 用 jss_db 用 户 登 录, 查 看 当 前 可 访 问 的 数 据 库 : (jss_db@192.168.30.243) [(none)]> show databases; +--------------------+ Database +--------------------+ information_schema jssdb +--------------------+ 2 rows in set (0.00 sec) jssdb 库 倒 是 列 出 来 了, 但 是, 好 奇 怪 呀! 不 是 说 只 授 予 了 jssdb 库 的 权 限 吗, 怎 么 还 能 看 到 information_schema 库 呢? 别 急, 咱 们 马 上 就 会 提 到 这 一 点 1. 并 不 存 在 的 INFORMATION_SCHEMA 库 熟 悉 Oracle 数 据 库 的 朋 友 想 必 知 道, 在 Oracle 数 据 库 中 有 一 堆 v$* 视 图 user_* all_* 等 字 典 表, 所 有 能 够 成 功 连 接 数 据 库 的 用 户 都 可 以 访 问 这 些 对 象 ( 无 需 额 外 授 权 ) MySQL 数 据 库 中 也 存 在 一 系 列 这 样 的 对 象, 比 如 TABLES VIEWS COLUMNS 等 等, 所 有 能 够 成 功 登 录 到 MySQL 数 据 库 的 用 户 都 能 访 问 想 一 想, 这 些 对 象 在 哪 呢? 没 错, 正 是 在 INFORMATION_SCHEMA 数 据 库 下 既 然 这 类 对 象 能 够 被 访 问, 那 么 INFORMATION_SCHEMA 库 自 然 也 就 能 被 所 有 用 户 看 到 啦, 这 样 才 符 合 逻 辑 需 要 注 意 的 是,MySQL 中 的 INFORMATION_SCHEMA 并 不 是 真 正 的 数 据 库, 在 操 作 系 统 层 并 没 有 与 之 对 应 的 物 理 文 件, 这 个 数 据 库 及 库 中 的 对 象 全 是 由 MySQL 自 动 维 护 的 一 系 列 虚 拟 对 象, 这 些 对 象 用 户 能 看 却 不 能 改 ( 不 能 直 接 改 ), 并 且 与 Oracle 数 据 库 中 的 数 据 字 典 表 类 似, 用 户 查 询 这 些 对 象 中 的 记 录 时, 看 到 的 都 是 自 己 有 权 限 看 到 的 对 象 比 如 说 拥 有 jssdb 库 创 建 权 限 的 jss_db 用 户, 能 够 在 INFORMATION_SCHEMA 数 据 库 的 TABLES/COLUMNS 等 对 象 中, 查 看 jssdb 库 中 所 有 表 和 列 的 信 息, 但 是 因 为 没 有 视 图 过 程 这 类 对 象 的 操 作 权 限, 访 问 VIEWS 字 典 表 时, 就 查 看 不 到 记 录 啦! INFORMATION_SCHEMA 库 中 对 象 的 另 一 特 殊 之 处 在 于, 用 户 不 能 对 INFORMATION_SCHEMA 数 据 库 中 的 对 象 做 授 权 比 如 将 information_schema.tables 表 对 象 的 SELECT 权 限 授 予 某 个 用 户, 这 样 操 作 肯 定 会 失 败, 即 使 是 管 理 员 用 户 也 不 行 2. 有 趣 的 test 库 除 了 INFORMATION_SCHEMA 这 样 的 虚 拟 库 外,MySQL 数 据 库 中 的 test 库 的 默 认 权
限 也 需 要 引 起 DBA 们 注 意 新 建 MySQL 数 据 库 后, 默 认 创 建 的 test 数 据 库 权 限 比 较 怪 异, 所 有 可 连 接 的 用 户 都 能 够 拥 有 权 限 访 问 该 库, 并 操 作 其 中 的 对 象 这 是 怎 么 实 现 的 呢? 其 实 很 简 单, 查 看 库 级 权 限 字 典 表 mysql.db, 您 就 明 白 了 : mysql> select * from mysql.db where db like 'test%'\g; *************************** 1. row *************************** Host: % Db: test User: Select_priv: Y Insert_priv: Y Update_priv: Y Delete_priv: Y Create_priv: Y Drop_priv: Y Grant_priv: N References_priv: Y Index_priv: Y Alter_priv: Y Create_tmp_table_priv: Y Lock_tables_priv: Y Create_view_priv: Y Show_view_priv: Y Create_routine_priv: Y Alter_routine_priv: N Execute_priv: N Event_priv: Y Trigger_priv: Y *************************** 2. row *************************** Host: % Db: test\_% User: Select_priv: Y Insert_priv: Y Update_priv: Y Delete_priv: Y Create_priv: Y Drop_priv: Y Grant_priv: N References_priv: Y Index_priv: Y Alter_priv: Y Create_tmp_table_priv: Y Lock_tables_priv: Y Create_view_priv: Y Show_view_priv: Y Create_routine_priv: Y Alter_routine_priv: N
Execute_priv: N Event_priv: Y Trigger_priv: Y 2 rows in set (0.00 sec) 你 看, 从 权 限 上 来 看,Host 为 %,User 为 空, 这 就 说 明 了 不 限 制 的, 所 有 能 连 接 到 MySQL 的 用 户, 全 都 拥 有 test 及 test 开 头 的 数 据 库 的 几 乎 所 有 权 限 这 无 疑 存 在 安 全 上 的 隐 患, 先 不 说 在 其 中 创 建 的 重 要 对 象 可 被 任 何 人 访 问, 就 算 该 库 中 没 有 任 何 对 象, 假 如 有 人 想 恶 意 破 坏 DB 服 务, 只 要 登 录 数 据 库 后, 在 该 库 创 建 一 个 超 大 对 象, 把 空 闲 空 间 全 部 占 满, 就 相 当 于 变 相 达 到 了 破 坏 DB 服 务 的 目 的 对 于 这 类 权 限 没 啥 好 客 气 的, 该 咋 处 理 就 咋 处 理 吧! 不 过 如 果 读 者 朋 友 是 按 照 三 思 在 本 书 中 介 绍 的 步 骤 创 建 数 据 库, 那 就 不 会 存 在 这 种 隐 患 了, 还 记 得 第 3 章 中 配 置 数 据 库 环 境 时 我 们 做 过 的 操 作 吗 : (root@localhost) [(none)]> truncate table mysql.db; 直 接 清 空 mysql.db 表 中 记 录, 这 两 个 权 限 已 被 删 除, 隐 患 早 已 经 被 排 除 啦! 顺 便 提 出 一 个 问 题, 如 果 想 让 所 有 用 户 都 拥 有 访 问 jssdb 库 中 对 象 的 权 限,GRANT 语 句 应 该 怎 么 写 呢? 有 兴 趣 的 朋 友 不 妨 在 自 己 的 测 试 环 境 中 模 拟 一 下 吧! 5.3.3 表 表 作 为 具 体 的 对 象, 当 我 们 谈 论 到 对 某 个 对 象 授 权 时, 已 经 进 入 到 一 个 相 对 细 粒 度 的 权 限 级 别 了, 表 对 象 的 授 权 信 息 保 存 在 mysql.tables_priv 字 典 表 中 我 知 道 很 多 初 学 者 在 学 习 MySQL 权 限 操 作 时, 由 于 对 权 限 体 系 了 解 有 限 不 够 熟 悉, 甚 至 可 能 不 清 楚 究 竟 有 哪 些 权 限 可 供 授 权 这 个 问 题 解 决 起 来 也 很 简 单, 直 接 看 官 方 文 档, 文 档 中 的 表 5-2 罗 列 了 所 有 可 授 予 的 权 限 当 然 啦 看 本 书 也 靠 谱, 前 面 5.2.2 节 中 列 的 表 就 是 抄 ( 提 起 这 个 字 儿 我 脸 就 红 了 ) 自 官 方 文 档 的 权 限 列 表, 里 面 各 种 权 限 明 细 写 得 清 清 楚 楚 明 明 白 白, 看 完 后 记 住 就 不 会 再 迷 茫 啦! 还 有 些 朋 友 文 档 也 没 少 看, 可 就 是 记 不 住, 一 方 面 由 于 权 限 类 型 多 ( 其 实 MySQL 中 的 权 限 相 比 Oracle 已 经 少 太 多 了 ), 另 一 方 面 权 限 还 分 了 多 个 粒 度, 谁 能 记 得 清 哪 个 粒 度 都 有 哪 些 权 限 哪 针 对 这 种 情 况 也 很 好 解 决, 用 desc 查 看 相 关 表 对 象 的 结 构 即 可 比 方 说, 现 在 咱 们 都 不 知 道 在 表 一 级, 究 竟 能 够 授 予 用 户 什 么 样 的 权 限 ( 或 者 说 用 户 有 什 么 样 的 选 择 ), 那 么 直 接 使 用 desc mysql.tables_priv 查 看, 例 如 : (system@localhost) [(none)]> desc mysql.tables_priv; +-------------+--------------+------+-----+----------+------------+ Field Type Null Key Default Extra +-------------+--------------+------+-----+----------+------------+ Host char(60) NO PRI Db char(64) NO PRI User char(16) NO PRI Table_name char(64) NO PRI