mysql用户权限管理与权限授予语法

1次阅读

grant语句需明确作用对象、权限类型和生效范围,mysql 8.0起须先create user再grant,禁用隐式建用户;权限验证应实测而非仅依赖show grants。

mysql用户权限管理与权限授予语法

GRANT 语句的基本写法和权限粒度

MySQL 的权限控制是分层的,GRANT 不是“给用户赋一个权限”那么简单,而是必须明确「作用对象」+「权限类型」+「生效范围」。漏掉任何一项都可能授错权,或根本不起作用。

常见错误是只写 GRANT select ON *.* 却没指定用户和主机,结果命令执行成功但权限没落到目标账户上。

  • 权限类型要精确:比如 SELECTINSERTUPDATE 是表级;CREATEDROP数据库级;RELOADSHUTDOWN 是全局管理权限
  • 作用对象格式为 db_name.tbl_name* 表示所有库,*.* 表示所有库所有表,`mydb`.* 表示 mydb 库下所有表(注意反引号用于转义含特殊字符的库名)
  • 用户标识必须带主机:如 'appuser'@'192.168.1.%''admin'@'localhost',不写主机名默认是 'user'@'%',但新版本 MySQL 8.0+ 默认禁用 % 匹配本地连接

MySQL 8.0+ 与旧版本在权限语法上的关键差异

MySQL 8.0 彻底重构了权限系统,最大的变化是把以前隐式包含的权限(如 USAGE)显式化,并废弃了部分旧语法。直接沿用 5.7 的脚本在 8.0 上会报错。

典型报错:Error 1410 (42000): You are not allowed to create a user with GRANT —— 这是因为 8.0 默认关闭了 create_user_priv 自动授予,且要求先 CREATE USERGRANT

  • 必须先显式创建用户:
    CREATE USER 'dev'@'%' IDENTIFIED BY 'p@ssw0rd';
  • 再授权:
    GRANT SELECT, INSERT ON `testdb`.* TO 'dev'@'%';
  • 刷新权限仍需:FLUSH PRIVILEGES;,但仅在手动修改 mysql.user 表后才真正必要;用 GRANT 命令操作后权限立即生效
  • WITH GRANT OPTION 依然可用,但授予该权限的用户不能跨主机代理(例如 'a'@'%' WITH GRANT OPTION 无法给 'b'@'10.0.0.5' 授权)

常见误授场景:哪些权限看起来安全实则危险

开发常以为只给 SELECT 就够安全,但忽略元数据访问和执行上下文风险。有些权限表面普通,组合使用却可导致信息泄露甚至提权。

  • SHOW DATABASES:默认关闭,但一旦开启,用户能看到所有库名,可能暴露测试/备份库路径
  • FILE 权限:允许读写服务器文件系统(如 SELECT ... INTO OUTFILELOAD DATA INFILE),配合 SELECT 可能读取 /etc/passwd 或 MySQL 配置文件
  • PROCESS:能看到其他用户正在执行的 SQL,含敏感条件或临时表名
  • EXECUTE:如果数据库里有定义好的存储过程,且该过程内含 INSERT/UPDATE,那么仅授 EXECUTE 就等价于间接授了写权限

验证权限是否生效的可靠方式

别只信 SHOW GRANTS for 'u'@'h'; 的输出,它只显示「被授予的语句」,不反映最终生效权限(比如被 REVOKE 后未刷缓存,或角色权限未激活)。最准的方式是切到该用户连接后实测。

  • 用目标用户登录:
    mysql -u dev -p -h db.example.com
  • 检查当前有效权限:
    SELECT * FROM INFORMATION_SCHEMA.ROLE_TABLE_GRANTS WHERE GRANTEE = "'dev'@'%'" G

    (8.0+ 角色场景)或更通用的

    SHOW GRANTS;
  • 直接尝试敏感操作,例如:
    DROP TABLE IF EXISTS test; -- 看是否报 ERROR 1142
  • 注意:权限检查是逐层匹配的,MySQL 优先匹配最具体的规则(如 'u'@'192.168.1.100''u'@'%' 优先),所以主机名精度比用户名更重要

权限系统里最易被忽略的是「撤销后残留」——REVOKE 不会自动清除用户账号,也不会影响已建立的活跃连接。连接保持期间旧权限仍然有效,直到断开重连。

text=ZqhQzanResources