MySQL 案例:用户鉴权与 Host 优先级
前言
MySQL 鉴权的方式是 Username 和 Host 两个维度的,最近遇到了一些关于登录时到底是被 MySQL 识别为哪个账号的问题,因此简单梳理一下 MySQL 匹配账号的优先级。
简要分析
MySQL 在创建用户的时候,一般是需要指定用户名和来源 IP 的,比如:
mysql> show grants for test@'%';
+----------------------------------+
| Grants for test@% |
+----------------------------------+
| GRANT USAGE ON *.* TO 'test'@'%' |
+----------------------------------+
1 row in set (0.00 sec)
由于 Host 这个字段支持正则匹配,因此这个字段设置为 % 的时候,则代表所有的来源 IP 都能匹配到。
因为这个特性,所以有时候创建的账号会有如下的情况出现:
+------+---------------+
| user | host |
+------+---------------+
| test | % |
| test | 10.104.% |
| test | 10.104.56.136 |
+------+---------------+
参考官方文档的描述:
When multiple matches are possible, the server must determine which of them to use. It resolves this issue as follows: 1.Whenever the server reads the user table into memory, it sorts the rows. 2.When a client attempts to connect, the server looks through the rows in sorted order. 3.The server uses the first row that matches the client host name and user name. The server uses sorting rules that order rows with the most-specific Host values first.
简而言之:MySQL 会按照 Host 的匹配精度,按降序排列同一个 Username 的所有账号,当 Client 端尝试登录 MySQL 的时候,会按照顺序依次这个 Username 下面所有的 Host 规则,直到匹配成功。
Host 这个字段不仅能填 IP,也能写域名,同样也能利用到正则表达式匹配:
由于域名指向的 IP 受 DNS 的影响,因此多数时候会用 IP,一般来说需要 DNS 来屏蔽一些后端细节的时候才会用域名来作为 Host 字段的值。
测试一下
使用如下操作创建三个用户,密码不做区分:
mysql> create user test@'%' identified by 'test';
Query OK, 0 rows affected (0.00 sec)
mysql> create user test@'10.104.56.136' identified by 'test';
Query OK, 0 rows affected (0.00 sec)
mysql> create user test@'10.104.%' identified by 'test';
Query OK, 0 rows affected (0.01 sec)
mysql>
mysql>
mysql>
mysql> select user,host from mysql.user where user='test' order by host desc;
+------+---------------+
| user | host |
+------+---------------+
| test | 10.104.56.136 |
| test | 10.104.% |
| test | % |
+------+---------------+
3 rows in set (0.00 sec)
mysql>
PS:order by desc 仅为展示上的考虑。
那么从两个不同的机器上(10.104.56.136 和 10.104.43.107)尝试登录 MySQL,按照文档的描述,匹配的优先级应该是:10.104.56.136->10.104.%->%
。那么有一台服务器能完整匹配到 IP,另外一台服务器匹配到的应该是10.104.%
。
实际操作一下看看效果:
root@debian:~# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.104.56.136 ......(省略)
root@debian:~# mysql -h192.168.1.100 -utest -ptest
......(省略)
Server version: 5.7.18-txsql-log 20200331
......(省略)
mysql> show grants;
+----------------------------------------------+
| Grants for test@10.104.56.136 |
+----------------------------------------------+
| GRANT USAGE ON *.* TO 'test'@'10.104.56.136' |
+----------------------------------------------+
1 row in set (0.00 sec)
mysql>
在另外一台机器上:
root@VM-43-107-debian:~# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.104.43.107 ......(省略)
root@debian:~# mysql -h192.168.1.100 -utest -ptest
......(省略)
Server version: 5.7.18-txsql-log 20200331
......(省略)
mysql> show grants;
+-----------------------------------------+
| Grants for test@10.104.% |
+-----------------------------------------+
| GRANT USAGE ON *.* TO 'test'@'10.104.%' |
+-----------------------------------------+
1 row in set (0.00 sec)
mysql>
换成本地的设备再试一下登录:
Tomo@MacBook-Pro ~ % mysql -hgz-cdb.sql.tencentcdb.com -utest -ptest -P59888
......(省略)
Server version: 5.7.18-txsql-log 20200331
......(省略)
mysql> show grants;
+----------------------------------+
| Grants for test@% |
+----------------------------------+
| GRANT USAGE ON *.* TO 'test'@'%' |
+----------------------------------+
1 row in set (0.02 sec)
mysql>
可以看到本地设备的 IP 由于和前两个匹配规则不一致,所以最后匹配到了 % 的这个账号。
总结一下
作为比较保险的办法,尽量少用 Host 来区分不同的账号,直接用不同的 Username 会比较好管理和维护,如果一定需要用 Host 来区分,那么至少也要用不同的密码,防止匹配到了错误的用户,导致权限不足引起业务上的问题。
课外题
localhost 和 127.0.0.1 算是常用的两个 Host,可以作为实践内容动手试一下,体验一下匹配的规律。在 MySQL 看来,精确的域名和精确的 IP 是同等地位的。
- 异步加载的基本逻辑与浏览器抓包一般流程
- 左手用R右手Python系列之——表格数据抓取之道
- XML/HTML/JSON——数据抓取过程中不得不知的几个概念
- R语言网络数据抓取的又一个难题,终于攻破了!
- R语言数据清洗实战——高效list解析方案
- 左手用R右手Python系列——循环中的错误异常规避
- SpringBoot2.x开发案例之整合Quartz任务管理系统
- 给出一组非负整数,重新排序组成最大的数
- [机智的机器在学习] TensorFlow实现Kmeans聚类
- [机智的机器在学习] 利用TensorFlow实现多元线性回归分类器
- [数据结构和算法]《算法导论》动态规划笔记(1)
- [数据结构和算法]《算法导论》动态规划笔记(2)
- [算法与数据结构] 《算法导论》堆排序笔记
- [数据结构与算法] 链表的其他类型
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- ClickHouse王炸功能即将来袭?
- 搭建Amoeba实现MySQL主从数据库读写分离
- 如何在centos7上看墙外的世界
- 远程仓库的使用
- 破解某交(y)友(p)app的VIP&&半自动im机器人
- 关于compareTo使用的几种情况
- 高通量数据中批次效应的鉴定和处理(二)
- 通过ansible管理docker容器
- HBASE 技术细节 读取与写入 Region Split与合并介绍
- django2.2+Daphne+nginx+supervisor 生产环境部署
- Python 爬虫进阶必备 | 趣解某不可逆加密(短文警告)
- confluence6.3安装与破解
- git分支
- git使用介绍
- jenkins添加git地址时报错问题