开源社区推送的这篇文章《故障分析 | 密码使用特殊字符》,介绍了密码中包含特殊字符的情况,算是一个常见的场景,可以将这个问题增加到自己的案例知识库中。
背景
最近在使用脚本新建了一批应用用户,发现一个奇怪的问题,有部分用户存在以下问题:应用使用该密码能正常访问,但使用mysql客户端登录手动输入密码无法登录。
经过与正常用户对比发现存在登录异常的用户使用了特殊字符"$"。
问题复现
在测试环境使用脚本生成一批用户,
#新建用户脚本简化后如下#!/bin/bashpw="abc$2UY"mysql--login-path=root-e"createuserapp@'%'identifiedby'$pw'"mysql--login-path=root-e"grantinsert,update,delete,selecton*.*toapp@'%'"#测试使用mysql客户端登录[root@node3~]#mysql-h127.0.0.1-uapp-p#手动输入密码无法登录Enterpassword:ERROR1045(28000):Accessdeniedforuser'app'@'127.0.0.1'(usingpassword:YES)[root@node3~]#mysql-h127.0.0.1-uapp-p'abc$2UY'#使用单引号无法登录mysql:[Warning]Usingapasswordonthecommandlineinterfacecanbeinsecure.ERROR1045(28000):Accessdeniedforuser'app'@'127.0.0.1'(usingpassword:YES)[root@node3~]#mysql-h127.0.0.1-uapp-pabc$2UY#不加单引号或使用双引号都可以登录mysql:[Warning]mandsendwith;or\g.YourMySQLconnectionidis15389Serverversion:8.0.18MySQLCommunityServer-GPLCopyright(c)2000,,Oracleand/oritsaffiliates.Allrightsreserved.OracleisaregisteredtrademarkofOracleCorporationand/oritsaffiliates.Othernamesmaybetrademarksoftheirrespectiveowners.Type'help;'or'\h'forhelp.Type'\c'toclearthecurrentinputstatement.mysql>
问题分析
根据上面的测试,发现部分能登录部分不能登录。那为什么部分可以,部分不可以?
首先可以确认一下存入数据库的密码是否正确。
我们可以手动新建一个用户密码与app用户密码保持一致。然后比较mysql.user表中authentication_string字段是否一致。
mysql>createusertest@'%'identifiedby'abc$2UY';QueryOK,0rowsaffected(0.05sec)mysql>selectuser,host,authentication_stringfrommysql.userwhereuserin('app','test');+------+------+-------------------------------------------+|user|host|authentication_string|+------+------+-------------------------------------------+|app|%|*06E0B7BA0149152EE2A387A144A2DF9ACC492297||test|%|*7258A15F121DD9F6F7C40C08D34A3DB5ED8C8CB5|+------+------+-------------------------------------------+
通过对比authentication_string字段发现两个密码不一致,说明脚本生成的用户密码并不是原来的密码了。为什么会这样呢?
我们知道在shell中使用单引号与双引号定义的字符串是有些区别的,
[root@node3~]#echo"abc$2UY"abcUY[root@node3~]#echo'abc$2UY'abc$2UY[root@node3~]#echoabc$2UYabcUY
单引号定义字符串所见即所得,双引号引用的内容,所见非所得。如果内容中有命令、变量等,会先把变量、命令解析出结果,然后再输出最终内容。分析到这回头看脚本密码使用了双引号导致了$2被解析成了空,最终存入数据库的密码为:abcUY。使用mysql登录时密码加单引号或手动输入密码此时$2没有被解析成空,与数据库中的密码不一致无法登录,而密码加双引号或不加时$2被解析成空,刚好和数据库的密码一致此时能正常登录数据库。
下面我们新建一个用户密码设置成:abcUY,验证一下。
mysql>createusertest1@'%'identifiedby'abcUY';QueryOK,0rowsaffected(0.03sec)mysql>selectuser,host,authentication_stringfrommysql.userwhereuserin('app','test','test1');+-------+------+-------------------------------------------+|user|host|authentication_string|+-------+------+-------------------------------------------+|app|%|*06E0B7BA0149152EE2A387A144A2DF9ACC492297||test|%|*7258A15F121DD9F6F7C40C08D34A3DB5ED8C8CB5||test1|%|*06E0B7BA0149152EE2A387A144A2DF9ACC492297|+-------+------+-------------------------------------------+
比较用户app与test1的authentication_string字段发现一致,说明app密码确实是abcUY 。其实不止$符会有这个问题,其它特殊字符也会存上以上问题。所以在新建用户或登录数据库时如果密码包含特殊字符需要注意是否会被解析的问题。
另外在使用login-path免密登录配置时,如果密码包含“#”符号,存在一个 bug(/bug.php?id=95597)正常配置的密码无法登录到数据库,需要加上双引号。测试如下:
mysql>createuserapp2@'%'identifiedby'123#abc';QueryOK,0rowsaffected(0.01sec)[root@node3~]#mysql_config_editorset--login-path=app--user=app2--host=127.0.0.1-pEnterpassword:输入123#abc[root@node3~]#mysql--login-path=appERROR1045(28000):Accessdeniedforuser'app2'@'127.0.0.1'(usingpassword:YES)#规避这个bug也很简单,配置时输入密码加上双引号[root@node3~]#mysql_config_editorset--login-path=app--user=app2--host=127.0.0.1-pEnterpassword:输入"123#abc"[root@node3~]#mysql--login-path=mandsendwith;or\g.YourMySQLconnectionidis15542Serverversion:8.0.18MySQLCommunityServer-GPLCopyright(c)2000,,Oracleand/oritsaffiliates.Allrightsreserved.OracleisaregisteredtrademarkofOracleCorporationand/oritsaffiliates.Othernamesmaybetrademarksoftheirrespectiveowners.Type'help;'or'\h'forhelp.Type'\c'toclearthecurrentinputstatement.mysql>
该bug在MySQL 5.7.33,MySQL 8.0.23修复。
因此,
1. 在创建密码时尽量避免使用$#等特殊字符,以免产生不必要的困扰。如果一定要使用请加上单引号或加上转义字符\。
2. 在MySQL 5.7.33与MySQL 8.0.23版本前使用login-path时密码存在"#"时,配置时输入密码需要加上双引号。
如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,
近期更新的文章:
《企业IT运维故障定位方法及工具》
《技术高手是如何炼成的?》
《中国民航安全运行的最强大脑》
《新书推荐 - 《MySQL高可用解决方案》》
《Oracle 23c数据库的10个特性介绍》
近期的热文:
《"红警"游戏开源代码带给我们的震撼》
文章分类和索引:
《公众号1000篇文章分类和索引》