<ins id="jxy61"><option id="jxy61"><menu id="jxy61"></menu></option></ins>
          1. 煉數成金 門戶 大數據 Mysql 查看內容

            MySQL 8.0的Public Key Retrival錯誤,毫無規律可言怎么破?

            2021-3-12 17:15| 發布者: 煉數成金_小數| 查看: 16370| 評論: 0|原作者: 農行數風云團隊|來自: DBAplus社群

            摘要: 所在部門的連接數據庫的方法有JDBC、JDBCTemplate、C3P0連接池和Druid連接池等技術,在這些連接實現方法上筆者都觀察到出現過上述的錯誤。該錯誤有一定的特性,就是偶爾會出現該錯誤,該錯誤并不會一直出現,該錯誤 ...
            作者介紹
            農行研發中心“數風云”團隊,一支朝氣蓬勃、快速成長的技術團隊,始終致力于農行大數據、數據庫和云計算等領域的應用實踐與技術創新,探索數據賦能,勇攀數據云巔,為企業數字化轉型和金融科技發展不斷貢獻力量。

            一、背景介紹
            近期筆者所在部門在使用MySQL時,經常會出現如下錯誤,且這個錯誤并不會一直出現,屬于某種偶發性的錯誤:


            筆者所在部門的連接數據庫的方法有JDBC、JDBCTemplate、C3P0連接池和Druid連接池等技術,在這些連接實現方法上筆者都觀察到出現過上述的錯誤。該錯誤有一定的特性,就是偶爾會出現該錯誤,該錯誤并不會一直出現,該錯誤的出現沒有明顯的規律。而且筆者發現,底層使用JDBC連接驅動的情況下,無論上層是采用何種數據源實現技術,筆者的部門都發現會報上述錯誤。

            針對上述錯誤,在筆者所在部門的軟硬件環境下,筆者對MySQL為何會產生這個問題、這個問題產生的條件、MySQL官方文檔對這個問題的闡述、如何有效避免與解決這個問題等方面在本文進行了詳細的分析與解釋。希望能夠幫助到真正遇到這個問題的DBA與開發人員。

            二、環境介紹
            1、實驗構架
            筆者所在部門使用的MySQL版本為8.0.18版本,MySQL使用組復制技術保證高可用,即MySQL Group Replication(MGR)。筆者復現問題以及實驗的架構如下圖所示:

            圖2.1  實驗所采用的構架

            本測試使用的MySQL MGR集群搭建在虛擬機之上,虛擬機的詳細硬件配置如下表所示:

            表2.1  詳細硬件配置

            為了充分測試各種類型的連接數據庫的方式在筆者所在部門使用的MySQL上的表現,筆者分別測試JDBC、JDBCTemplate、C3P0以及Druid方式連接數據庫,參與測試的軟件版本如下表所示:

            表2.2  參與測試的軟件版本

            三、問題報錯展示
            在使用JDBC連接時,可能會出現“Public Key Retrieval is not allowed”的錯誤,從錯誤的Java堆棧信息中可以看出,該錯誤是在JDBC與MySQL建立Connection對象時出現的,該錯誤的錯誤堆棧如下圖所示:

            圖3.1  JDBC錯誤堆棧

            在使用C3P0連接池時,也會出現“Public Key Retrieval is not allowed”的錯誤,從錯誤的Java堆棧信息中可以看出,該錯誤仍是在JDBC與MySQL建立Connection對象時出現,該錯誤會導致C3P0連接池在初始化時失敗,該錯誤的錯誤堆棧如下圖所示:

            圖3.2  C3P0錯誤堆棧

            在使用Druid連接池時,也會出現“Public Key Retrieval is not allowed”的錯誤,與C3P0連接池一樣,會導致Druid連接池在初始化時失敗,該錯誤的錯誤堆棧如下圖所示:

            圖3.3  Druid錯誤堆棧

            四、問題分析
            筆者在查閱了網上關于“Public Key Retrieval is not allowed”錯誤的資料后,發現大多數網上關于該問題的博文對該問題的解釋都存在一定的紕漏。首先需要明確的是出現該問題的時候,MySQL配置的密碼認證插件為如下兩種:

            sha256_password
            caching_sha2_password

            值得注意的是,如果使用“mysql_native_password”密碼認證插件,不會出現“Public Key Retrieval is not allowed”錯誤。MySQL配置的密碼認證方式可以通過如下命令進行查看。


            接著筆者來詳細分析“Public Key Retrieval is not allowed”錯誤產生的原因。首先MySQL 8.0默認推薦使用“sha256_password”和“caching_sha2_password”這兩種認證插件。只有較老的MySQL版本仍然會使用“mysql_native_password”。
            根據MySQL提供的官方文檔(https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html),這兩種插件都是使用SHA256算法來對密碼進行保護。這些插件的具體執行流程如下:

            檢查客戶端是否禁用SSL/TLS加密傳輸;
            如果客戶端未禁用SSL/TLS加密傳輸,則客戶端在進行認證時的認證報文(傳輸用戶名和密碼的報文)是使用TLS進行傳輸的,兩種插件認為認證報文傳輸安全,不進行任何其他操作;
            如果客戶端禁用SSL/TLS加密傳輸,則客戶端在進行認證時的認證報文(傳輸用戶名和密碼的報文)是使用明文進行傳輸的,兩種插件認為認證報文傳輸不安全,會單獨對明文報文中的密碼使用RSA加密方式進行加密。

            1、啟用SSL/TLS加密傳輸的客戶端認證流程
            如上述流程所述,當客戶端未禁用SSL/TLS加密傳輸時,通過Wireshark等抓包工具可以觀察到整個客戶端與MySQL服務端交互的過程都被TLS協議加密保護了。如下圖所示:

            圖4.1  啟用TLS協議MySQL傳輸報文

            雖然會產生登錄的明文報文,但是該明文報文中的用戶信息為空,真正的用戶信息在TLS握手階段后的密文中。如下圖所示:

            圖4.2  啟用TLS協議MySQL登錄數據包詳情

            2、禁用SSL/TLS加密傳輸的客戶端認證流程
            如上述流程所述,當客戶端禁用SSL/TLS加密傳輸時(比如JDBC連接串設置useSSL=false參數),用戶的登錄信息會在明文中進行傳輸,如下圖所示:

            圖4.3  禁用TLS協議MySQL傳輸報文

            明文傳輸密碼存在安全問題,此時,兩種插件會嘗試使用RSA加密(RSA encryption)方法對明文報文中的密碼部分進行加密,加密后的密碼部分如下圖所示:

            圖4.4  啟用TLS協議MySQL登錄數據包詳情

            五、解決方案
            根據前面的分析,導致“Public Key Retrieval is not allowed”主要是由于當禁用SSL/TLS協議傳輸后,客戶端會使用服務器的公鑰進行傳輸,默認情況下客戶端不會主動去找服務器拿公鑰,此時就會出現上述錯誤。

            經過查閱官方文檔,出現Public Key Retrieval的場景可以概括為在禁用SSL/TLS協議傳輸切當前用戶在服務器端沒有登錄緩存的情況下,客戶端沒有辦法拿到服務器的公鑰。具體的場景如下:

            新建數據庫用戶,首次登錄;
            數據庫的用戶名、密碼發生改變后登錄;
            服務器端調用FLUSH PRIVELEGES指令刷新服務器緩存。

            針對上述錯誤,有如下的解決方案:
            在條件允許的情況下,不要禁用SSL/TLS協議,即不要在CLI客戶端使用--ssl-mode=disabled,或在JDBC連接串中加入useSSL=false;
            如果必須禁用SSL/TLS協議,則可以嘗試使用CLI客戶端登錄一次MySQL數據庫制造登錄緩存;
            如果必須禁用SSL/TLS協議,則可以通過增加如下參數允許客戶端獲得服務器的公鑰:
            在JDBC連接串中加入allowPublicKeyRetrieval=true參數;
            在CLI客戶端連接時加入--get-server-public-key參數;
            在CLI客戶端連接時加入--server-public-key-path=file_name參數,指定存放在本地的公鑰文件。

            聲明:文章收集于網絡,版權歸原作者所有,為傳播信息而發,如有侵權,請聯系小編刪除,謝謝!

            歡迎加入本站公開興趣群
            軟件開發技術群
            興趣范圍包括:Java,C/C++,Python,PHP,Ruby,shell等各種語言開發經驗交流,各種框架使用,外包項目機會,學習、培訓、跳槽等交流
            QQ群:26931708

            Hadoop源代碼研究群
            興趣范圍包括:Hadoop源代碼解讀,改進,優化,分布式系統場景定制,與Hadoop有關的各種開源項目,總之就是玩轉Hadoop
            QQ群:288410967 

            鮮花

            握手

            雷人

            路過

            雞蛋

            相關閱讀

            最新評論

            熱門頻道

            • 大數據

            即將開課

             

            GMT+8, 2021-4-9 05:55 , Processed in 0.300712 second(s), 25 queries .

            年轻人手机在线观看