首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 連接 MySQL 5.x 認證協議不兼容問題完整解決方案

     編輯:PHP 相關知識

前言:MySQL 4.1+ 引入的新認證機制

MySQL 4.1 引入基於 SHA-1 的雙重雜湊認證插件 (mysql_native_password),密文長度從 16 字節變為 41 字節。舊版 PHP MySQL 擴展 (ext/mysql) 使用舊版客戶端庫,不支援新協議,導致連接失敗:Client does not support authentication protocol。本文系統梳理 5 種官方解決方案及現代最佳實踐。

方案對比表

方案操作優點缺點推薦場景
1. 升級客戶端庫更新 PHP、MySQL 驅動至支援新協議版本 (mysqli, PDO_MySQL, mysqlnd)徹底解決,享受新安全特性需更新代碼 (ext/mysql 已棄用/移除)✅ 所有新專案、現有專案重構
2. 使用舊帳號連接用 4.1 前創建的用戶 (舊雜湊)無需改代碼/配置新用戶無法用,安全性低,不擴展⚠️ 臨時過渡
3. 重置密碼為舊格式SET PASSWORD FOR 'user'@'host' = OLD_PASSWORD('newpwd'); 或 UPDATE mysql.user SET Password=OLD_PASSWORD('newpwd') ...; FLUSH PRIVILEGES;兼容舊驅動,保留用戶降低安全性 (單次 SHA-1,無鹽),不符合合規⚠️ 必須維舊系統、無法升級驅動時
4. 啟動 mysqld --old-passwords配置 [mysqld] old_passwords=1 重啟全局強制舊格式所有新密碼均為弱雜湊,喪失新協議優勢❌ 不推薦
5. 批量修復已升級帳號SELECT Host,User FROM mysql.user WHERE LENGTH(Password)>16; 逐個 SET PASSWORD ... = OLD_PASSWORD(...)修復存量同方案 3,降級安全⚠️ 遷移期間臨時用

現代最佳實踐:徹底告別 ext/mysql

1. 使用 mysqli 或 PDO_MySQL (PHP 5.0+ 內建)

<?php
// mysqli 面向對象
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
if ($mysqli->connect_errno) die("Connect failed: " . $mysqli->connect_error);
$mysqli->set_charset('utf8mb4');

// PDO (推薦,跨數據庫)
$pdo = new PDO('mysql:host=localhost;dbname=db;charset=utf8mb4', 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
    PDO::MYSQL_ATTR_SSL_CA => '/path/to/ca.pem', // 可選 SSL
]);

兩者均基於 mysqlnd (MySQL Native Driver),原生支援 mysql_native_password、caching_sha2_password (MySQL 8.0 默認) 等現代認證插件。

2. MySQL 8.0+ 默認認證插件變更

MySQL 8.0 默認 caching_sha2_password,舊版 PHP (7.1 以下) mysqlnd 不支援。解決:

  • 升級 PHP ≥ 7.2 (mysqlnd 內建支援)。
  • 或創建用戶指定舊插件:CREATE USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY 'pass';。
  • 或修改全局默認:[mysqld] default_authentication_plugin=mysql_native_password (不推薦,降級安全)。

3. 驗證連接協議

<?php
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
echo "Protocol version: " . $mysqli->protocol_version . "\n";
echo "Client info: " . $mysqli->get_client_info() . "\n";
echo "Server info: " . $mysqli->get_server_info() . "\n";

遷移檢查清單

  1. ✅ PHP 版本 ≥ 7.2 (建議 8.1+),啟用 pdo_mysql、mysqli 擴展。
  2. ✅ 代碼全量替換 mysql_* 函數為 mysqli 或 PDO。
  3. ✅ 所有查詢使用預處理語句,綁定參數。
  4. ✅ 字符集統一 utf8mb4 (連接、表、列)。
  5. ✅ MySQL 用戶使用 mysql_native_password 或 caching_sha2_password (PHP 7.2+ 支援)。
  6. ✅ 禁用 OLD_PASSWORD()、--old-passwords,確保密碼雜湊強度。
  7. ✅ 連接配置 SSL/TLS (生產環境強制)。

結語

認證協議不兼容本質是舊生態與新安全標準的衝突。唯一正確的路徑是升級驅動、升級代碼、擁抱現代認證。方案 3/4/5 皆為「降級安全」的權宜之計,僅用於無法升級的極端場景並配合風險驗收。投入精力重構數據庫訪問層,不僅解決連接問題,更能獲得預處理防注入、事務支援、異步查詢、類型化綁定等現代能力,是技術債務清償的高回報投資。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved