MySQL 8.0+ 创建用户不强制指定认证插件,但默认使用 caching_sha2_password,旧客户端可能因不支持而报错;需根据客户端兼容性显式指定 mysql_native_password 或保留默认,并注意 host 匹配、权限授予及密码过期策略。

MySQL 8.0+ 创建用户必须指定认证插件?
不是“必须”,但不显式指定,CREATE USER 会按服务器默认插件创建——而 MySQL 8.0 默认是 caching_sha2_password。老应用连不上、客户端报 Client does not support authentication protocol,八成是这个原因。
实操建议:
- 若用 MySQL 5.7 或旧版客户端(如某些 Python 2.x 驱动、老版 Navicat),优先显式指定
mysql_native_password插件:CREATE USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123';
- 若确认客户端支持 SHA2(如 MySQL Shell、新版 Connector/J、PyMySQL ≥ 0.9.3),可保留默认:
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'pwd123';
- 执行后可用
SELECT plugin FROM mysql.user WHERE User = 'app_user';确认实际插件
host 部分写 '%' 还是 'localhost'?
这决定连接来源:用 '%' 允许任意 IP(包括本机通过 TCP 连),'localhost' 只匹配 Unix socket 连接(跳过 TCP 栈)。两者互不覆盖,CREATE USER 'u'@'%' 和 CREATE USER 'u'@'localhost' 是两个独立账号。
常见错误现象:
- 用户在命令行用
mysql -u app_user -p能连,但程序用127.0.0.1连失败 → 实际走的是 TCP,但只建了'app_user'@'localhost' - 想限制仅内网访问,却写了
'%'→ 应改用'192.168.1.%'或具体子网 - 测试环境图省事全用
'%',上线被扫描爆破 → 生产环境避免'%',至少限定 CIDR 段
CREATE USER 后为什么还连不上?
CREATE USER 只建账号、设密码、选插件,不赋任何权限。没权限 = 连得上但执行 SELECT 就报 Access denied。
必须补授权:
- 最小权限原则:只给业务需要的库表,例如
GRANT SELECT, INSERT ON mydb.orders TO 'app_user'@'%';
- 别漏
FLUSH PRIVILEGES;—— MySQL 8.0+ 大部分情况不用,但如果你手动改过mysql.user表,就得刷;普通GRANT会自动生效 - 权限变更后,旧连接不会实时失效,新连接才受控
MySQL 5.7 和 8.0 的 CREATE USER 语法差异
核心区别在密码设置方式和默认行为,不是语法报错,而是语义不同。
关键点:
- MySQL 5.7 支持
IDENTIFIED BY 'pwd'直接设密,且默认插件是mysql_native_password - MySQL 8.0 同样支持该写法,但默认插件变为
caching_sha2_password,且password_expired默认为Y(首次登录强制改密) - 若要兼容旧习惯,建用户时加
PASSWORD EXPIRE NEVER:CREATE USER 'app_user'@'%' IDENTIFIED BY 'pwd123' PASSWORD EXPIRE NEVER;
- MySQL 8.0 不再允许用
INSERT INTO mysql.user手动插用户,必须走CREATE USER或ALTER USER
最常被忽略的是 host 匹配逻辑和权限分离设计:建用户 ≠ 有权限,localhost ≠ 127.0.0.1,% 不等于安全可控。这些不是配置错误,是 MySQL 的权限模型本身如此。










