CREATE USER 之后必须用 GRANT 显式授权
MySQL 8.0+ 默认禁用
GRANT创建用户的功能,
CREATE USER只建账号、不附带任何权限,哪怕
USAGE(连接权限)也不会自动赋予。直接登录会报错:
Access denied for user 'xxx'@'%' (using password: YES),即使密码正确。
实操建议:
先执行CREATE USER 'devuser'@'localhost' IDENTIFIED BY 'strongpass123';再执行
GRANT SELECT, INSERT ON mydb.* TO 'devuser'@'localhost';最后别忘
FLUSH PRIVILEGES;—— 虽然多数情况下非必需(MySQL 8.0+ 权限表变更后会自动重载),但加了更稳妥
GRANT 时 host 写法决定连接来源范围
'user'@'localhost'和
'user'@'%'是两个完全独立的账号,权限互不影响。生产环境慎用
'%',尤其不能配
root或高权限账号。
常见误操作:
用GRANT ... TO 'app'@'%';后发现从本地连不上:因为 MySQL 优先匹配
'app'@'localhost'(如果存在),而该账号可能没建或没授权 应用部署在 Docker 或远程服务器,却只给了
'user'@'localhost',导致连接被拒 想限制仅某网段访问?用
'user'@'192.168.1.%'或
'user'@'10.0.0.5',比
%更安全
避免直接 GRANT ALL PRIVILEGES 给业务账号
ALL PRIVILEGES包含
DROP、
ALTER、
CREATE USER、
GRANT OPTION等高危权限。业务应用只需最小必要集,比如 Web 后端通常只需要
SELECT、
INSERT、
UPDATE、
DELETE。
特别注意:
GRANT OPTION允许该用户再给别人授权,一旦泄露等于权限失控
FILE权限可读写服务器文件系统,配合
SELECT ... INTO OUTFILE可能导致敏感信息导出 如需临时调试,可用
SHOW GRANTS FOR 'devuser'@'localhost';查看当前实际生效权限
MySQL 8.0 的角色(ROLE)机制更适合权限分组管理
手动给每个用户重复
GRANT SELECT, INSERT, UPDATE ON appdb.orders TO ...容易出错且难维护。用角色可抽象权限集合:
CREATE ROLE 'app_writer'; GRANT SELECT, INSERT, UPDATE ON appdb.* TO 'app_writer'; GRANT 'app_writer' TO 'service_user'@'%'; SET DEFAULT ROLE 'app_writer' TO 'service_user'@'%';
后续新增表只需更新角色权限,所有绑定该角色的用户自动继承。但注意:
SET DEFAULT ROLE必须显式执行,否则新用户登录后不会自动激活角色。
容易被忽略的一点:角色本身也受
host限定,
CREATE ROLE 'r1'@'localhost'和
CREATE ROLE 'r1'是不同对象 —— 大多数场景下省略
@host即可,默认为
@'%'。
