作者:王祥
爱可生 DBA 团队成员,次要负责 MySQL 故障解决和性能优化。对技术执着,为客户负责。
本文起源:原创投稿
* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
背景
最近在应用脚本新建了一批利用用户,发现一个奇怪的问题,有局部用户存下以下问题:利用应用该明码能失常拜访,但应用 mysql 客户端登录手动输出明码无奈登录。通过与失常用户比照发现存在登录异样的用户应用了特殊字符 ”$”。
问题复现
在测试环境应用脚本生成一批用户
# 新建用户脚本简化后如下
#!/bin/bash
pw="abc$2UY"
mysql --login-path=root -e"create user [email protected]'%'identified by'$pw'"mysql --login-path=root -e"grant insert,update,delete,select on *.* to [email protected]'%'"
#测试应用 mysql 客户端登录
[[email protected] ~]# mysql -h127.0.0.1 -uapp -p #手动输出明码无奈登录
Enter password:
ERROR 1045 (28000): Access denied for user 'app'@'127.0.0.1' (using password: YES)
[[email protected] ~]# mysql -h127.0.0.1 -uapp -p'abc$2UY' #应用单引号无奈登录
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'app'@'127.0.0.1' (using password: YES)
[[email protected] ~]# mysql -h127.0.0.1 -uapp -pabc$2UY #不加单引号或应用双引号都能够登录
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 15389
Server version: 8.0.18 MySQL Community Server - GPL
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
问题剖析
失常的话上述登录形式都是能够失常登录数据库的,那为什么局部能够局部不能够呢?首先能够确认一下存入数据库的明码是否正确。咱们能够手动新建一个用户明码与 app 用户明码保持一致。而后比拟 mysql.user 表中 authentication_string 字段是否统一。
mysql> create user [email protected]'%' identified by 'abc$2UY';
Query OK, 0 rows affected (0.05 sec)
mysql> select user,host,authentication_string from mysql.user where user in ('app','test');
+------+------+-------------------------------------------+
| user | host | authentication_string |
+------+------+-------------------------------------------+
| app | % | *06E0B7BA0149152EE2A387A144A2DF9ACC492297 |
| test | % | *7258A15F121DD9F6F7C40C08D34A3DB5ED8C8CB5 |
+------+------+-------------------------------------------+
通过比照 authentication_string 字段发现两个明码不统一,阐明脚本生成的用户明码并不是原来的明码了。为什么会这样呢?咱们晓得在 shell 中应用单引号与双引号定义的字符串是有区别的。如下:
[[email protected] ~]# echo "abc$2UY"
abcUY
[[email protected] ~]# echo 'abc$2UY'
abc$2UY
[[email protected] ~]# echo abc$2UY
abcUY
单引号定义字符串所见即所得,双引号援用的内容,所见非所得。如果内容中有命令、变量等,会先把变量、命令解析出后果,而后再输入最终内容。剖析到这回头看脚本明码应用了双引号导致了 $2 被解析成了空,最终存入数据库的明码为:abcUY。应用 mysql 登录时明码加单引号或手动输出明码此时 $2 没有被解析成空,与数据库中的明码不统一无奈登录,而明码加双引号或不加时 $2 被解析成空,刚好和数据库的明码统一此时能失常登录数据库。上面咱们新建一个用户明码设置成:abcUY,验证一下。
mysql> create user [email protected]'%' identified by 'abcUY';
Query OK, 0 rows affected (0.03 sec)
mysql> select user,host,authentication_string from mysql.user where user in ('app','test','test1');
+-------+------+-------------------------------------------+
| user | host | authentication_string |
+-------+------+-------------------------------------------+
| app | % | *06E0B7BA0149152EE2A387A144A2DF9ACC492297 |
| test | % | *7258A15F121DD9F6F7C40C08D34A3DB5ED8C8CB5 |
| test1 | % | *06E0B7BA0149152EE2A387A144A2DF9ACC492297 |
+-------+------+-------------------------------------------+
比拟用户 app 与 test1 的 authentication_string 字段发现统一,阐明 app 明码的确是 abcUY。其实不止 $ 符会有这个问题,其它特殊字符也会存上以上问题。所以在新建用户或登录数据库时如果明码蕴含特殊字符须要留神是否会被解析的问题。
另外在应用 login-path 免密登录配置时,如果明码蕴含“#”符号,存在一个 bug(https://bugs.mysql.com/bug.ph…)失常配置的明码无奈登录到数据库,须要加上双引号。测试如下:
mysql> create user [email protected]'%' identified by '123#abc';
Query OK, 0 rows affected (0.01 sec)
[[email protected] ~]# mysql_config_editor set --login-path=app --user=app2 --host=127.0.0.1 -p
Enter password: 输出 123#abc
[[email protected] ~]# mysql --login-path=app
ERROR 1045 (28000): Access denied for user 'app2'@'127.0.0.1' (using password: YES)
#躲避这个 bug 也很简略,配置时输出明码加上双引号
[[email protected] ~]# mysql_config_editor set --login-path=app --user=app2 --host=127.0.0.1 -p
Enter password: 输出 "123#abc"
[[email protected] ~]# mysql --login-path=app
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 15542
Server version: 8.0.18 MySQL Community Server - GPL
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
该 bug 在 MySQL 5.7.33,MySQL 8.0.23 修复。
总结
1. 新建用户及登录用户时如果明码存在特殊字符须要留神特殊字符会被解析成其它字符,需加上单引号或加上转义字符 \。
2. 在 MySQL 5.7.33 与 MySQL 8.0.23 版本前应用 login-path 时明码存在 ”#” 时,配置时输出明码须要加上双引号。