1. 程式人生 > 實用技巧 >談談java的mysql驅動中NonRegisteringDriver.connect(String url, Properties info)方法的bug

談談java的mysql驅動中NonRegisteringDriver.connect(String url, Properties info)方法的bug

最近在前端同學的推薦下,嘗試了一個做API前後端解耦的開源專案(開源專案連線:https://github.com/TommyLemon/APIAuto)。

問題發現:部署demo的過程中,發現了java的mysql驅動的bug,jar包版本:8.0.16。

問題剖析:

  1、發現專案在啟動連線db的時候一直報認證失敗(Access denied for user 'customercentor'@'10.63.66.144' (using password: YES)),確認了資料庫連線資訊,其他專案是可以連線成功的,說明是工程有問題。

  2、debug工程,發現專案裡用的是NonRegisteringDriver.connect(String url, Properties info)方法,其中把使用者名稱和密碼以引數的形式放在了url中,引數物件info為空。

   jdbc:mysql://localhost:3306/cutest?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&user=test&password=Cust23mtER_56#

  3、繼續追蹤,發現mysql驅動是支援這種寫法的,如下圖,在解析連線資訊的時候,它會首先去info中試圖獲得連線資訊,當獲得為null的時候,就會呼叫自己的下面的程式碼試圖從url中解析出需要的連線認證資訊(ip、埠、使用者名稱、密碼)

   4、繼續debug,發現他底層使用了java的java.util.regex.Matcher類,其中設定了正則表示式模板:

private static final Pattern CONNECTION_STRING_PTRN = Pattern.compile("(?<scheme>[\\w:%]+)\\s*(?://(?<authority>[^/?#]*))?\\s*(?:/(?!\\s*/)(?<path>[^?#]*))?(?:\\?(?!\\s*\\?)(?<query>[^#]*))?(?:\\s*#(?<fragment>.*))?");

  如上圖,問題就出現在密碼解析的這裡,在解析密碼的時候,它使用了 (?<query>[^#]*)) 導致如果密碼帶有#號,就會解析錯誤,我的密碼是Cust23mtER_56# ,解析之後變成了Cust23mtER_56,所以連線資料庫的時候會報認證失敗,因為密碼確實錯了!!!!

  綜上,這就是為什麼你百度搜索“java Access denied for user 'customercentor'@'10.63.66.144' (using password: YES)”的時候會找到博文說在獲得mysql資料庫連線的時候,不要把使用者名稱和密碼以引數的形式&到url的後面了。

https://blog.csdn.net/lvhaoguang0/article/details/80868821