文档信息
- MySQL 版本: 8.0+
- 适用场景: 生产环境、开发环境、测试环境
- 安全级别: 包含安全最佳实践建议
- 更新日期: 2025-12-22
目录
1. MySQL 8.0 认证机制变化
1.1 默认认证插件变更
MySQL 5.7 vs 8.0 对比
| 特性 | MySQL 5.7 | MySQL 8.0 |
|---|---|---|
| 默认认证插件 | mysql_native_password |
caching_sha2_password |
| 密码加密强度 | SHA1(较弱) | SHA256(强) |
| SSL/TLS 要求 | 可选 | 首次连接必需 |
| Root 默认主机 | % 或 localhost |
localhost |
| 密码验证策略 | 宽松 | 严格(默认启用 validate_password) |
新认证插件特点
caching_sha2_password:
sql
-- 查看认证插件
SELECT user, host, plugin FROM mysql.user WHERE user='root';
优势:
- ✅ SHA-256 哈希算法,安全性更高
- ✅ 支持密码缓存,提高性能
- ✅ 支持多种认证方式
限制:
- ⚠️ 旧版客户端(< 5.7)不支持
- ⚠️ 某些应用需要显式指定支持
1.2 密码验证策略(validate_password)
MySQL 8.0 默认启用密码验证组件:
sql
-- 查看密码策略配置
SHOW VARIABLES LIKE 'validate_password%';
输出示例:
+--------------------------------------+--------+
| Variable_name | Value |
+--------------------------------------+--------+
| validate_password.check_user_name | ON |
| validate_password.length | 8 |
| validate_password.mixed_case_count | 1 |
| validate_password.number_count | 1 |
| validate_password.policy | MEDIUM |
| validate_password.special_char_count | 1 |
+--------------------------------------+--------+
策略级别:
- LOW: 仅检查长度(最小 8 位)
- MEDIUM: 长度 + 数字 + 大小写 + 特殊字符
- STRONG: MEDIUM + 字典检查
2. 远程登录配置步骤
2.1 方案一:创建独立的远程 Root 用户(推荐)
步骤 1:登录 MySQL
bash
# Windows
cd "C:\Program Files\MySQL\MySQL Server 8.0\bin"
mysql -uroot -p
# Linux
mysql -uroot -p
步骤 2:创建远程用户
sql
-- 方式 1:允许任意 IP 访问(开发环境)
CREATE USER 'root'@'%' IDENTIFIED BY 'YourStrongPassword123!';
-- 方式 2:仅允许特定 IP(推荐)
CREATE USER 'root'@'192.168.1.100' IDENTIFIED BY 'YourStrongPassword123!';
-- 方式 3:允许特定网段
CREATE USER 'root'@'192.168.1.%' IDENTIFIED BY 'YourStrongPassword123!';
-- 方式 4:允许特定域名
CREATE USER 'root'@'app.example.com' IDENTIFIED BY 'YourStrongPassword123!';
密码要求(MEDIUM 策略):
- ✅ 至少 8 个字符
- ✅ 包含大写字母
- ✅ 包含小写字母
- ✅ 包含数字
- ✅ 包含特殊字符(如 !@#$%)
步骤 3:授予完整权限
sql
-- 授予所有权限(等同于 root)
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
-- 刷新权限
FLUSH PRIVILEGES;
权限说明:
ALL PRIVILEGES: 所有权限*.*: 所有数据库的所有表WITH GRANT OPTION: 允许该用户授权给其他用户
步骤 4:验证用户创建
sql
-- 查看用户列表
SELECT user, host, plugin, account_locked FROM mysql.user;
-- 查看权限
SHOW GRANTS FOR 'root'@'%';
预期输出:
sql
+-----------------------------------------------+
| Grants for root@% |
+-----------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO `root`@`%` |
| WITH GRANT OPTION |
+-----------------------------------------------+
2.2 方案二:修改现有 Root 用户主机(不推荐)
⚠️ 安全警告:此方法会修改 localhost 的 root 用户,可能导致本地管理权限问题。
sql
-- 查看当前 root 用户
SELECT user, host FROM mysql.user WHERE user='root';
-- 修改主机为 %(允许任意 IP)
UPDATE mysql.user SET host='%' WHERE user='root' AND host='localhost';
-- 刷新权限
FLUSH PRIVILEGES;
风险:
- ❌ 本地无法使用
root@localhost登录 - ❌ 违反最小权限原则
- ❌ 不符合安全最佳实践
2.3 配置 MySQL 服务器绑定地址
修改配置文件
Windows : C:\ProgramData\MySQL\MySQL Server 8.0\my.ini
Linux : /etc/my.cnf 或 /etc/mysql/my.cnf
ini
[mysqld]
# 允许所有 IP 连接(默认为 127.0.0.1)
bind-address = 0.0.0.0
# 或绑定特定网卡 IP
# bind-address = 192.168.1.100
# 端口(默认 3306)
port = 3306
# 最大连接数
max_connections = 500
重启 MySQL 服务
Windows:
powershell
# 方法 1:服务管理器
sc stop MySQL80
sc start MySQL80
# 方法 2:管理工具
net stop MySQL80
net start MySQL80
Linux:
bash
# SystemD
sudo systemctl restart mysql
# SysV
sudo service mysql restart
验证绑定地址
bash
# Windows
netstat -ano | findstr :3306
# Linux
netstat -tuln | grep 3306
ss -tuln | grep 3306
预期输出:
TCP 0.0.0.0:3306 0.0.0.0:0 LISTENING
0.0.0.0表示监听所有网卡127.0.0.1表示仅本地访问
2.4 配置防火墙规则
Windows 防火墙
方法 1:图形界面
控制面板 → Windows Defender 防火墙 → 高级设置 → 入站规则 → 新建规则
规则类型:端口
协议:TCP
端口:3306
操作:允许连接
配置文件:根据需要选择(域、专用、公用)
名称:MySQL 8.0 Remote Access
方法 2:命令行
powershell
# 允许 3306 端口入站
netsh advfirewall firewall add rule name="MySQL 8.0" dir=in action=allow protocol=TCP localport=3306
# 查看规则
netsh advfirewall firewall show rule name="MySQL 8.0"
# 删除规则(如需要)
netsh advfirewall firewall delete rule name="MySQL 8.0"
Linux 防火墙
firewalld (CentOS/RHEL 7+):
bash
# 永久开放 3306 端口
sudo firewall-cmd --permanent --add-port=3306/tcp
# 或添加 MySQL 服务
sudo firewall-cmd --permanent --add-service=mysql
# 重载防火墙
sudo firewall-cmd --reload
# 查看规则
sudo firewall-cmd --list-all
iptables (传统方式):
bash
# 允许 3306 端口
sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
# 保存规则
sudo iptables-save > /etc/iptables/rules.v4
# 查看规则
sudo iptables -L -n
ufw (Ubuntu/Debian):
bash
# 允许 3306 端口
sudo ufw allow 3306/tcp
# 或指定来源 IP
sudo ufw allow from 192.168.1.0/24 to any port 3306
# 启用防火墙
sudo ufw enable
# 查看状态
sudo ufw status
2.5 处理认证插件兼容性
问题场景
旧版客户端或应用连接 MySQL 8.0 时报错:
Authentication plugin 'caching_sha2_password' cannot be loaded
解决方案 1:使用兼容插件(临时方案)
sql
-- 为远程用户设置旧版认证插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'YourPassword123!';
-- 刷新权限
FLUSH PRIVILEGES;
⚠️ 安全提示 :mysql_native_password 安全性较低,仅在必要时使用。
解决方案 2:升级客户端(推荐)
确保客户端库版本支持 caching_sha2_password:
- MySQL Connector/J: 8.0.9+
- mysql-connector-python: 8.0.16+
- PHP mysqli: PHP 7.4+
- Node.js mysql2: 2.0.0+
解决方案 3:修改默认认证插件
全局设置(my.ini/my.cnf):
ini
[mysqld]
# 设置默认认证插件为兼容模式
default_authentication_plugin=mysql_native_password
重启 MySQL 后,新建用户将默认使用 mysql_native_password。
2.6 SSL/TLS 配置(可选但推荐)
MySQL 8.0 默认启用 SSL,但可能需要配置:
查看 SSL 状态
sql
SHOW VARIABLES LIKE '%ssl%';
强制用户使用 SSL
sql
-- 创建用户时强制 SSL
CREATE USER 'root'@'%' IDENTIFIED BY 'Password123!' REQUIRE SSL;
-- 修改现有用户
ALTER USER 'root'@'%' REQUIRE SSL;
-- 取消 SSL 要求
ALTER USER 'root'@'%' REQUIRE NONE;
客户端连接示例
bash
# 使用 SSL 连接
mysql -h 192.168.1.100 -u root -p --ssl-mode=REQUIRED
# 不使用 SSL(如果服务器允许)
mysql -h 192.168.1.100 -u root -p --ssl-mode=DISABLED
3. 安全加固方案
3.1 最小权限原则(推荐生产环境)
不要直接开放 root@'%',而是创建特定用途的账户:
sql
-- 应用程序专用账户(只读权限)
CREATE USER 'app_read'@'192.168.1.%' IDENTIFIED BY 'AppReadPass123!';
GRANT SELECT ON myapp_db.* TO 'app_read'@'192.168.1.%';
-- 应用程序专用账户(读写权限)
CREATE USER 'app_write'@'192.168.1.%' IDENTIFIED BY 'AppWritePass123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON myapp_db.* TO 'app_write'@'192.168.1.%';
-- 备份专用账户
CREATE USER 'backup'@'192.168.1.10' IDENTIFIED BY 'BackupPass123!';
GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON *.* TO 'backup'@'192.168.1.10';
-- 监控专用账户
CREATE USER 'monitor'@'192.168.1.20' IDENTIFIED BY 'MonitorPass123!';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'monitor'@'192.168.1.20';
-- 刷新权限
FLUSH PRIVILEGES;
3.2 IP 白名单机制
方式 1:数据库层面
sql
-- 只允许特定 IP 段访问
CREATE USER 'admin'@'10.0.0.0/255.255.255.0' IDENTIFIED BY 'Password123!';
-- MySQL 8.0.23+ 支持 CIDR 表示法
CREATE USER 'admin'@'10.0.0.0/24' IDENTIFIED BY 'Password123!';
方式 2:防火墙层面
bash
# Linux iptables - 只允许特定 IP
sudo iptables -A INPUT -p tcp -s 192.168.1.100 --dport 3306 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 3306 -j DROP
# firewalld - 创建富规则
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="3306" accept'
3.3 密码策略强化
sql
-- 查看当前密码策略
SHOW VARIABLES LIKE 'validate_password%';
-- 设置为 STRONG 级别
SET GLOBAL validate_password.policy=STRONG;
-- 设置最小密码长度
SET GLOBAL validate_password.length=12;
-- 设置密码过期策略
ALTER USER 'root'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;
-- 设置密码重用限制
SET GLOBAL password_history=5; -- 不能重用最近 5 个密码
SET GLOBAL password_reuse_interval=365; -- 365 天内不能重用
配置文件持久化(my.ini/my.cnf):
ini
[mysqld]
# 密码策略
validate_password.policy=STRONG
validate_password.length=12
validate_password.mixed_case_count=2
validate_password.number_count=2
validate_password.special_char_count=2
# 密码过期和重用
default_password_lifetime=90
password_history=5
password_reuse_interval=365
3.4 连接限制
sql
-- 限制最大连接数
ALTER USER 'root'@'%' WITH MAX_CONNECTIONS_PER_HOUR 100;
ALTER USER 'root'@'%' WITH MAX_QUERIES_PER_HOUR 10000;
-- 查看用户资源限制
SELECT user, host, max_connections, max_user_connections
FROM mysql.user WHERE user='root';
全局配置:
ini
[mysqld]
max_connections=500
max_user_connections=50
max_connect_errors=10
3.5 审计日志(Enterprise)
MySQL 企业版支持审计插件:
sql
-- 安装审计插件
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
-- 配置审计规则
SET GLOBAL audit_log_policy='ALL';
SET GLOBAL audit_log_format='JSON';
社区版替代方案:
- 使用 General Log(性能影响大)
- 使用 ProxySQL 进行审计
- 使用操作系统的审计功能(auditd)
4. 常见问题排查
4.1 连接被拒绝
错误信息
ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.1.100' (10061)
排查步骤
1. 检查 MySQL 服务状态
bash
# Windows
sc query MySQL80
# Linux
sudo systemctl status mysql
2. 检查端口监听
bash
# Windows
netstat -ano | findstr :3306
# Linux
ss -tuln | grep 3306
预期输出应包含 0.0.0.0:3306 而非 127.0.0.1:3306。
3. 检查防火墙
bash
# Windows
netsh advfirewall firewall show rule name=all | findstr MySQL
# Linux
sudo firewall-cmd --list-all
sudo iptables -L -n | grep 3306
4. 检查 bind-address
sql
SHOW VARIABLES LIKE 'bind_address';
应该是 0.0.0.0 或服务器 IP,而非 127.0.0.1。
4.2 认证失败
错误信息
ERROR 1045 (28000): Access denied for user 'root'@'192.168.1.100' (using password: YES)
排查步骤
1. 验证用户存在
sql
-- 在服务器本地登录
mysql -uroot -p
-- 查询用户
SELECT user, host, plugin FROM mysql.user WHERE user='root';
2. 检查主机匹配
sql
-- 查看允许的主机
SELECT user, host FROM mysql.user WHERE user='root';
如果只有 root@localhost,需要创建 root@'%' 或 root@'客户端IP'。
3. 验证密码
sql
-- 重置密码
ALTER USER 'root'@'%' IDENTIFIED BY 'NewPassword123!';
FLUSH PRIVILEGES;
4. 检查账户锁定
sql
SELECT user, host, account_locked FROM mysql.user WHERE user='root';
-- 如果被锁定,解锁
ALTER USER 'root'@'%' ACCOUNT UNLOCK;
4.3 认证插件不支持
错误信息
Authentication plugin 'caching_sha2_password' cannot be loaded:
dlopen(/usr/local/mysql/lib/plugin/caching_sha2_password.so, 2): image not found
解决方案
方案 1:修改用户认证插件
sql
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'Password123!';
FLUSH PRIVILEGES;
方案 2:升级客户端
- MySQL Workbench: 8.0+
- Navicat: 12.0+
- phpMyAdmin: 4.9+
- MySQL Connector: 对应语言的 8.0+ 版本
方案 3:在连接字符串中指定
bash
# JDBC
jdbc:mysql://192.168.1.100:3306/db?defaultAuthenticationPlugin=mysql_native_password
# Python
mysql.connector.connect(
host='192.168.1.100',
user='root',
password='Password123!',
auth_plugin='mysql_native_password'
)
4.4 SSL 连接问题
错误信息
ERROR 2026 (HY000): SSL connection error: error:00000001:lib(0):func(0):reason(1)
解决方案
1. 检查 SSL 配置
sql
SHOW VARIABLES LIKE '%ssl%';
2. 禁用 SSL 要求(临时)
sql
ALTER USER 'root'@'%' REQUIRE NONE;
3. 客户端显式指定 SSL 模式
bash
# 禁用 SSL
mysql -h 192.168.1.100 -u root -p --ssl-mode=DISABLED
# 可选 SSL
mysql -h 192.168.1.100 -u root -p --ssl-mode=PREFERRED
# 必需 SSL
mysql -h 192.168.1.100 -u root -p --ssl-mode=REQUIRED
4.5 密码验证策略限制
错误信息
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
解决方案
方案 1:使用符合策略的强密码
sql
-- 检查策略要求
SHOW VARIABLES LIKE 'validate_password%';
-- 使用符合要求的密码
ALTER USER 'root'@'%' IDENTIFIED BY 'StrongPass123!@#';
方案 2:临时降低策略级别(不推荐)
sql
SET GLOBAL validate_password.policy=LOW;
SET GLOBAL validate_password.length=6;
-- 修改密码
ALTER USER 'root'@'%' IDENTIFIED BY 'Simple1!';
-- 改回严格策略
SET GLOBAL validate_password.policy=MEDIUM;
SET GLOBAL validate_password.length=8;
5. 生产环境建议
5.1 安全清单
必须实施(Critical)
- ✅ 禁止使用 root@'%':创建专用管理账户
- ✅ 强密码策略:启用 validate_password,MEDIUM 或 STRONG
- ✅ IP 白名单:仅允许已知 IP 访问
- ✅ 定期更新密码:设置密码过期策略
- ✅ 防火墙规则:严格限制 3306 端口访问
推荐实施(High)
- ✅ 启用 SSL/TLS:加密传输数据
- ✅ 最小权限原则:按需分配权限
- ✅ 审计日志:记录所有管理操作
- ✅ 定期备份:包括用户权限表
- ✅ 监控连接:异常登录告警
可选实施(Medium)
- 📝 使用 VPN 或堡垒机访问
- 📝 启用双因素认证(需要插件)
- 📝 数据库连接池限制
- 📝 定期安全审计
5.2 账户管理策略
sql
-- 管理员账户(DBA 使用)
CREATE USER 'dba_admin'@'10.0.1.%' IDENTIFIED BY 'DbaAdminPass123!';
GRANT ALL PRIVILEGES ON *.* TO 'dba_admin'@'10.0.1.%' WITH GRANT OPTION;
-- 应用只读账户
CREATE USER 'app_reader'@'10.0.2.%' IDENTIFIED BY 'AppReadPass123!';
GRANT SELECT ON production_db.* TO 'app_reader'@'10.0.2.%';
-- 应用读写账户
CREATE USER 'app_writer'@'10.0.2.%' IDENTIFIED BY 'AppWritePass123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON production_db.* TO 'app_writer'@'10.0.2.%';
-- 备份账户
CREATE USER 'backup_user'@'10.0.3.10' IDENTIFIED BY 'BackupPass123!';
GRANT SELECT, LOCK TABLES, RELOAD, SHOW VIEW ON *.* TO 'backup_user'@'10.0.3.10';
-- 监控账户
CREATE USER 'monitor'@'10.0.4.%' IDENTIFIED BY 'MonitorPass123!';
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'monitor'@'10.0.4.%';
FLUSH PRIVILEGES;
5.3 连接配置最佳实践
my.ini/my.cnf 生产配置示例
ini
[mysqld]
# 网络配置
bind-address=0.0.0.0
port=3306
max_connections=500
max_connect_errors=100
# 认证配置
default_authentication_plugin=caching_sha2_password
# SSL 配置
require_secure_transport=ON # 强制使用 SSL
ssl_ca=/etc/mysql/ssl/ca.pem
ssl_cert=/etc/mysql/ssl/server-cert.pem
ssl_key=/etc/mysql/ssl/server-key.pem
# 密码策略
validate_password.policy=STRONG
validate_password.length=12
validate_password.mixed_case_count=2
validate_password.number_count=2
validate_password.special_char_count=2
default_password_lifetime=90
password_history=5
password_reuse_interval=365
# 性能配置
max_allowed_packet=256M
wait_timeout=28800
interactive_timeout=28800
# 日志配置
log_error=/var/log/mysql/error.log
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
# 字符集
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
5.4 监控与告警
监控指标
连接监控:
sql
-- 当前连接数
SHOW STATUS LIKE 'Threads_connected';
-- 最大连接数
SHOW VARIABLES LIKE 'max_connections';
-- 连接错误
SHOW STATUS LIKE 'Connection_errors%';
-- 详细连接信息
SELECT * FROM information_schema.processlist WHERE user='root';
失败登录监控:
sql
-- 查看错误日志
SELECT * FROM performance_schema.error_log
WHERE error_code IN (1045, 1130) -- Access denied, Host blocked
ORDER BY logged DESC LIMIT 50;
告警脚本示例(Linux)
bash
#!/bin/bash
# mysql_monitor.sh
# 配置
MYSQL_USER="monitor"
MYSQL_PASS="MonitorPass123!"
ALERT_EMAIL="admin@example.com"
MAX_CONNECTIONS_PERCENT=80
# 获取当前连接数
CURRENT=$(mysql -u$MYSQL_USER -p$MYSQL_PASS -e "SHOW STATUS LIKE 'Threads_connected';" | awk 'NR==2 {print $2}')
MAX=$(mysql -u$MYSQL_USER -p$MYSQL_PASS -e "SHOW VARIABLES LIKE 'max_connections';" | awk 'NR==2 {print $2}')
# 计算百分比
PERCENT=$((CURRENT * 100 / MAX))
# 告警
if [ $PERCENT -gt $MAX_CONNECTIONS_PERCENT ]; then
echo "Warning: MySQL connections at ${PERCENT}% (${CURRENT}/${MAX})" | \
mail -s "MySQL Connection Alert" $ALERT_EMAIL
fi
# 检查失败登录
FAILED=$(mysql -u$MYSQL_USER -p$MYSQL_PASS -e "SHOW STATUS LIKE 'Aborted_connects';" | awk 'NR==2 {print $2}')
if [ $FAILED -gt 100 ]; then
echo "Warning: $FAILED failed connection attempts" | \
mail -s "MySQL Security Alert" $ALERT_EMAIL
fi
添加到 crontab:
bash
# 每 5 分钟检查一次
*/5 * * * * /path/to/mysql_monitor.sh
5.5 定期维护任务
每日任务
sql
-- 1. 检查异常连接
SELECT user, host, COUNT(*) as connections
FROM information_schema.processlist
GROUP BY user, host
HAVING connections > 10;
-- 2. 检查锁定账户
SELECT user, host, account_locked
FROM mysql.user
WHERE account_locked='Y';
-- 3. 检查过期密码
SELECT user, host, password_expired
FROM mysql.user
WHERE password_expired='Y';
每周任务
sql
-- 1. 审查用户权限
SELECT user, host, GROUP_CONCAT(DISTINCT db) as databases
FROM mysql.db
GROUP BY user, host;
-- 2. 检查未使用的账户(需要配合日志)
SELECT user, host, password_last_changed
FROM mysql.user
WHERE password_last_changed < DATE_SUB(NOW(), INTERVAL 90 DAY);
每月任务
- 密码轮换(关键账户)
- 权限审计
- 安全补丁更新
- 访问日志分析
6. 应用程序连接示例
6.1 命令行连接
bash
# 基本连接
mysql -h 192.168.1.100 -P 3306 -u root -p
# 指定数据库
mysql -h 192.168.1.100 -u root -p mydb
# 使用 SSL
mysql -h 192.168.1.100 -u root -p --ssl-mode=REQUIRED
# 使用旧版认证插件
mysql -h 192.168.1.100 -u root -p --default-auth=mysql_native_password
# 执行 SQL 文件
mysql -h 192.168.1.100 -u root -p < script.sql
6.2 编程语言连接
Java (JDBC)
java
String url = "jdbc:mysql://192.168.1.100:3306/mydb" +
"?useSSL=true" +
"&requireSSL=true" +
"&allowPublicKeyRetrieval=true";
Connection conn = DriverManager.getConnection(
url,
"root",
"Password123!"
);
Python (mysql-connector-python)
python
import mysql.connector
config = {
'host': '192.168.1.100',
'port': 3306,
'user': 'root',
'password': 'Password123!',
'database': 'mydb',
'ssl_disabled': False,
'auth_plugin': 'caching_sha2_password'
}
conn = mysql.connector.connect(**config)
PHP (MySQLi)
php
<?php
$mysqli = new mysqli(
'192.168.1.100',
'root',
'Password123!',
'mydb',
3306
);
// 启用 SSL
$mysqli->ssl_set(NULL, NULL, '/path/to/ca.pem', NULL, NULL);
$mysqli->real_connect(
'192.168.1.100',
'root',
'Password123!',
'mydb',
3306,
NULL,
MYSQLI_CLIENT_SSL
);
?>
Node.js (mysql2)
javascript
const mysql = require('mysql2');
const connection = mysql.createConnection({
host: '192.168.1.100',
port: 3306,
user: 'root',
password: 'Password123!',
database: 'mydb',
ssl: {
rejectUnauthorized: true
}
});
connection.connect();
.NET (MySql.Data)
csharp
string connStr = "server=192.168.1.100;port=3306;" +
"user=root;password=Password123!;" +
"database=mydb;SslMode=Required;";
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open();
7. 故障恢复指南
7.1 忘记 Root 密码
Windows 环境
1. 停止 MySQL 服务
powershell
sc stop MySQL80
2. 跳过权限验证启动
powershell
# 创建 init 文件
echo ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword123!'; > C:\mysql-init.txt
# 使用 init 文件启动
"C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqld.exe" --defaults-file="C:\ProgramData\MySQL\MySQL Server 8.0\my.ini" --init-file=C:\mysql-init.txt --console
3. 正常重启
powershell
# Ctrl+C 停止上述进程
sc start MySQL80
# 删除 init 文件
del C:\mysql-init.txt
Linux 环境
1. 停止 MySQL
bash
sudo systemctl stop mysql
2. 跳过权限验证启动
bash
# 创建 init 文件
sudo cat > /tmp/mysql-init.sql << EOF
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword123!';
FLUSH PRIVILEGES;
EOF
# 使用 init 文件启动
sudo mysqld --init-file=/tmp/mysql-init.sql &
# 等待几秒
sleep 5
3. 正常重启
bash
# 停止临时进程
sudo killall mysqld
# 正常启动
sudo systemctl start mysql
# 删除 init 文件
sudo rm /tmp/mysql-init.sql
7.2 账户被锁定
sql
-- 查看锁定状态
SELECT user, host, account_locked FROM mysql.user WHERE user='root';
-- 解锁账户
ALTER USER 'root'@'%' ACCOUNT UNLOCK;
-- 清除连接错误计数
FLUSH HOSTS;
7.3 权限丢失
sql
-- 重新授予完整权限
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
-- 验证权限
SHOW GRANTS FOR 'root'@'%';
8. 安全审计清单
8.1 配置审计
sql
-- 1. 检查空密码账户(危险!)
SELECT user, host FROM mysql.user WHERE authentication_string='';
-- 2. 检查匿名用户(危险!)
SELECT user, host FROM mysql.user WHERE user='';
-- 3. 检查过于宽松的权限
SELECT user, host FROM mysql.user WHERE host='%' AND user='root';
-- 4. 检查不安全的认证插件
SELECT user, host, plugin FROM mysql.user
WHERE plugin='mysql_old_password';
-- 5. 检查 SSL 配置
SHOW VARIABLES LIKE '%ssl%';
-- 6. 检查密码策略
SHOW VARIABLES LIKE 'validate_password%';
-- 7. 检查连接限制
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'max_connect_errors';
8.2 加固建议
sql
-- 删除匿名用户
DELETE FROM mysql.user WHERE user='';
-- 删除 test 数据库
DROP DATABASE IF EXISTS test;
-- 删除远程 root(如果不需要)
DELETE FROM mysql.user WHERE user='root' AND host!='localhost';
-- 刷新权限
FLUSH PRIVILEGES;
9. 快速参考
9.1 常用命令速查
sql
-- 用户管理
CREATE USER 'user'@'host' IDENTIFIED BY 'password';
DROP USER 'user'@'host';
ALTER USER 'user'@'host' IDENTIFIED BY 'newpassword';
RENAME USER 'old'@'host' TO 'new'@'host';
-- 权限管理
GRANT ALL PRIVILEGES ON *.* TO 'user'@'host';
GRANT SELECT, INSERT ON db.* TO 'user'@'host';
REVOKE ALL PRIVILEGES ON *.* FROM 'user'@'host';
SHOW GRANTS FOR 'user'@'host';
-- 账户管理
ALTER USER 'user'@'host' ACCOUNT LOCK;
ALTER USER 'user'@'host' ACCOUNT UNLOCK;
ALTER USER 'user'@'host' PASSWORD EXPIRE;
ALTER USER 'user'@'host' REQUIRE SSL;
-- 刷新权限
FLUSH PRIVILEGES;
FLUSH HOSTS;
9.2 关键配置项
ini
[mysqld]
# 网络
bind-address=0.0.0.0
port=3306
# 认证
default_authentication_plugin=caching_sha2_password
# 密码
validate_password.policy=MEDIUM
validate_password.length=8
# SSL
require_secure_transport=ON
# 连接
max_connections=500
max_connect_errors=100
10. 总结
核心要点
- MySQL 8.0 默认更安全:新认证插件、密码策略、localhost 限制
- 远程访问三要素:用户权限 + 服务器配置 + 防火墙规则
- 安全优先:生产环境避免使用 root@'%',采用最小权限原则
- 兼容性处理:旧客户端需要切换到 mysql_native_password
- 持续监控:审计日志、连接监控、异常告警
推荐配置流程
sql
-- 1. 创建专用远程管理账户(而非 root)
CREATE USER 'db_admin'@'指定IP' IDENTIFIED BY 'StrongPassword123!';
-- 2. 授予必要权限
GRANT ALL PRIVILEGES ON *.* TO 'db_admin'@'指定IP' WITH GRANT OPTION;
-- 3. 设置安全选项
ALTER USER 'db_admin'@'指定IP' REQUIRE SSL;
ALTER USER 'db_admin'@'指定IP' PASSWORD EXPIRE INTERVAL 90 DAY;
-- 4. 刷新权限
FLUSH PRIVILEGES;
-- 5. 验证
SHOW GRANTS FOR 'db_admin'@'指定IP';
服务器配置:
ini
[mysqld]
bind-address=0.0.0.0
validate_password.policy=MEDIUM
require_secure_transport=ON
防火墙:仅开放到特定 IP 的 3306 端口。