Pokud se aplikace po přechodu na MySQL 8.4 přestala připojovat a server hlásí Plugin 'mysql_native_password' is not loaded, účet pořád používá starou přihlašovací metodu založenou na SHA-1 a MySQL 8.4 ji má ve výchozím stavu vypnutou. Z toho vedou dvě cesty. Skutečná oprava je přesunout účet na caching_sha2_password pomocí ALTER USER ... IDENTIFIED WITH caching_sha2_password BY '...', a to poté, co ověříš, že ovladač aplikace tuto metodu zná. Provizorní řešení je spustit server s mysql_native_password=ON, což funguje na 8.4 a nikde potom: MySQL 9.0 plugin úplně odstranilo. Podobně vypadající chyby, které vznikají na opačné straně - starý klient neumí caching_sha2_password, nebo nový klient 9.x už neumí mysql_native_password - mají vlastní opravy a rozlišit je je většina práce.
Tento článek se věnuje autentizační stránce upgradu na 8.4 do hloubky. Širší přehled změn mezi 8.0 a 8.4 je v článku MySQL 8.4 LTS: co se změnilo, vytváření účtů a přidělování oprávnění najdeš v článku Uživatelé a oprávnění v MySQL.
Co se změnilo, verze po verzi#
Plugin se z provozu stahuje už léta. Mezi verzemi se liší hlavně to, jak hlasitě na to MySQL upozorňuje.
| Verze | mysql_native_password | Výchozí pro nové účty |
|---|---|---|
| 5.7 | Dostupný, výchozí | mysql_native_password |
| 8.0 | Dostupný, zastaralý (varování od 8.0.34) | caching_sha2_password |
| 8.4 LTS | Přítomný, vypnutý, pokud ho při startu nezapneš | caching_sha2_password |
| 9.0 a novější | Odstraněn ze serveru | caching_sha2_password |
Roky s verzí 8.0 jsou důvod, proč tolik instalací stále má nativní účty. Výchozí hodnota se změnila v 8.0.4, jenže server povýšený z 5.7 nechal všechny stávající účty na starém pluginu a spousta návodů, souborů Docker Compose a hostingových panelů nastavuje default_authentication_plugin=mysql_native_password, aby se vyhnula potížím s ovladači. Takové účty fungovaly dál po celou řadu 8.0. Na 8.4 to končí.
Všimni si drobné, ale důležité věci v řádku pro 8.4. Plugin nezmizel: kód je pořád v serveru, účty, které ho používají, dál existují v mysql.user a data upgrade přežijí beze změny. Plugin se jen nenačte, takže přihlášení k takovému účtu nelze dokončit, stejně jako CREATE USER nebo ALTER USER, které ho jmenují. Na 9.x tytéž účty po upgradu také zůstanou, ale už neexistuje přepínač, kterým by se daly oživit.
Jak se oba pluginy liší#
mysql_native_password ukládá dvojitý hash hesla pomocí SHA-1, bez soli. Dva účty se stejným heslem mají stejný hash a SHA-1 je dost rychlé na to, aby šlo uniklou tabulku mysql.user levně prolomit hrubou silou. Samotné přihlášení je výzva a odpověď, při které se heslo nikdy neposílá, a proto dvacet let fungovalo i bez TLS.
caching_sha2_password ukládá hash SHA-256 se solí, provedený v tisících kol, takže útok na uložené hashe je mnohem dražší. Cenou je, že ověření hesla proti tomuto hashi je záměrně pomalé, a proto si server drží v paměti cache účtů, které se nedávno úspěšně přihlásily. Plugin má kvůli tomu dvě cesty:
- Rychlá autentizace - účet je v cache, klient tedy odpoví na výzvu odpovědí založenou na SHA-256 a je vpuštěn, aniž by heslo putovalo po síti. To je běžný případ.
- Plná autentizace - účet v cache není, což nastává při prvním přihlášení po startu serveru, po
FLUSH PRIVILEGESa po změně hesla účtu. Server potřebuje skutečné heslo, aby ho mohl porovnat s uloženým hashem, takže ho klient musí poslat, a MySQL ho přijme jen zabezpečeným kanálem: připojením přes TLS, přes Unix socket, nebo zašifrované veřejným klíčem RSA serveru.
Právě druhá cesta stojí za hlášeními typu „funguje to a pak zase ne“. Aplikace se připojuje bez TLS, několik dní je všechno v pořádku, protože účet je v cache, server se restartuje a další přihlášení selže, dokud se něco jednou nepřihlásí přes TLS a cache zase nezahřeje. Nastav klienta od začátku na TLS nebo na získání klíče RSA a problém se nikdy neobjeví.
Chyby a ze které strany pocházejí#
Každé selhání autentizace v této oblasti pochází z jedné ze tří situací: server nemůže spustit plugin účtu, klient nemůže spustit plugin, který server požadoval, nebo klient plugin spustit umí, ale spojení není pro plnou autentizaci dost zabezpečené.
| Chyba | Pochází z | Význam |
|---|---|---|
ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded | Server | Účet používá nativní plugin a server ho má vypnutý nebo odstraněný |
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded | Klient | Klientská knihovna je na nový plugin příliš stará |
ERROR 2059 (HY000): Authentication plugin 'mysql_native_password' cannot be loaded | Klient | Klient 9.x se připojuje k účtu nebo serveru, který stále používá starý plugin |
ERROR 2061 (HY000): ... Authentication requires secure connection | Klient | Plná autentizace přes nešifrované spojení bez klíče RSA |
Plugin 'mysql_native_password' is not loaded
Takhle ti server 8.4 nebo 9.x říká něco o účtu, ne o klientovi. Dostane to jakýkoli klient, ať je sebenovější, když se přihlašuje k účtu, jehož sloupec plugin stále říká mysql_native_password. Stejnou chybu dostaneš i jako chybu příkazu při spuštění CREATE USER ... IDENTIFIED WITH mysql_native_password - řádku, která se objevuje v mnoha starých instalačních návodech a provisioning skriptech. Oprav účet, nebo na 8.4 plugin zapni; na 9.x je možné jen to první.
Authentication plugin 'caching_sha2_password' cannot be loaded
Celá zpráva obvykle končí cestou, třeba /usr/lib/mysql/plugin/caching_sha2_password.so: cannot open shared object file. Klient je slinkovaný s knihovnou z éry MySQL 5.7 (nebo se starou klientskou knihovnou MariaDB), která o caching_sha2_password nikdy neslyšela, takže hledá soubor pluginu na disku a nic nenajde. Vytvoření toho souboru nepomůže. Aktualizuj klienta nebo ovladač; vracet účet zpět na nativní plugin je špatný směr, protože 9.x to neumí vůbec.
Authentication plugin 'mysql_native_password' cannot be loaded
Toto je zrcadlový případ a od doby, kdy se klienti 9.x objevili ve správcích balíčků, je častý - zvlášť ve formuli mysql v Homebrew. Klient 9.x už nativní plugin neobsahuje, takže připojení ke starému serveru 5.7, k serveru MariaDB nebo k účtu 8.x, který je pořád na starém pluginu, selže na straně klienta. Řešením je přesunout účet na caching_sha2_password, pokud to server podporuje, nebo pro servery, které to neumí, použít klienta 8.4 LTS (brew install mysql-client@8.4 na Macu).
Hlášky podle ovladačů
Ovladače, které protokol implementují samy, formulují stejná selhání jinak:
| Ovladač | Zpráva |
|---|---|
PHP mysqli / PDO, staré PHP | The server requested authentication method unknown to the client [caching_sha2_password] |
balíček mysql pro Node.js | ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server |
| Java Connector/J | Public Key Retrieval is not allowed |
Ta javová není problém s verzí: Connector/J plugin chápe, ale ve výchozím nastavení odmítá stahovat klíč RSA přes nešifrované spojení. Je to stejná situace plné autentizace jako u ERROR 2061, popsaná níže.
Najdi účty, které jsou stále na starém pluginu#
Než cokoli změníš, vypiš je. Spusť tohle jako root nebo jiný účet, který smí číst schéma mysql:
SELECT user, host, plugin, password_last_changedFROM mysql.userWHERE plugin = 'mysql_native_password'ORDER BY user, host;Čekej aplikační účty vytvořené starými skripty, účty přenesené ze serveru 5.7 pomocí dumpu a načtení (výstup SHOW CREATE USER s sebou nese plugin i hash) a občas i samotného root. Interní účty jako mysql.sys, mysql.session a mysql.infoschema používají na aktuálním serveru caching_sha2_password a jsou zamčené; nech je být.
Pamatuj, že účet je dvojice uživatele a hostitele, takže 'app'@'%' a 'app'@'localhost' jsou samostatné řádky a mohou používat různé pluginy. Aplikace, která se připojuje ze dvou míst, může narazit na problém jen z jednoho z nich. SELECT CURRENT_USER(); po přihlášení ukáže, kterému řádku relace skutečně odpovídá.
Kontrola upgradu v MySQL Shellu hlásí totéž v rámci širšího prověření, pokud před upgradem kontroluješ server 8.0:
$ mysqlsh root@db.example.net:3306 -- util check-for-server-upgrade --target-version=8.4.6Ověř klienta, než účet přesuneš#
Přesunutí účtu na caching_sha2_password dřív, než to jeho klient podporuje, vymění jednu odstávku za druhou. Cokoli vydané za posledních několik let je v pořádku; potíže dělají staré připíchnuté závislosti a staré systémové balíčky.
| Klient nebo ovladač | Podporuje caching_sha2_password |
|---|---|
PHP mysqli a PDO (mysqlnd) | Ano od PHP 7.4 |
Node.js mysql2 | Ano |
Node.js mysql (mysqljs) | Ne - přejdi na mysql2 |
| Python PyMySQL, mysql-connector-python | Ano v aktuálních vydáních |
| Java Connector/J | 8.0 a novější |
| .NET MySqlConnector, MySql.Data | Ano; MySql.Data od 8.0 |
Go go-sql-driver/mysql | 1.4 a novější |
mysql CLI, mysqldump | 8.0 a novější |
Několik praktických poznámek k řádkům výše.
PHP. Podpora byla přidána během řad 7.1 a 7.2, ale takhle staré PHP je dávno mimo bezpečnostní podporu a měl bys ho stejně aktualizovat. Na PHP 7.4 a každém vydání 8.x používají mysqli a pdo_mysql mysqlnd a zvládnou oba pluginy. Web na WordPressu nebo Laravelu, který selhává se zprávou „unknown to the client“, skoro vždy běží na starém binárním PHP někde, kde bys to nečekal - v cron kontejneru, v CLI na starém image - zatímco PHP webserveru je v pořádku. Možnosti připojení pokrývá článek PHP PDO a MySQL.
Node.js. Původní balíček mysql nikdy nepodporoval caching_sha2_password a prakticky se neudržuje. mysql2 má u většiny kódu téměř shodné API a podporuje oba pluginy i promises; u většiny projektů se změna omezí na název balíčku a řádek s importem. ORM jako Sequelize, Knex a TypeORM už ve svých aktuálních verzích pro MySQL používají mysql2.
Python. mysqlclient (modul MySQLdb) je obal kolem klientské knihovny v C, proti které byl sestaven, takže jeho podpora závisí na té knihovně, ne na jeho vlastní verzi. Wheel sestavený proti klientské knihovně MySQL 8 nebo novější funguje, ten sestavený proti staré knihovně ne.
Desktopové nástroje. MySQL Workbench 8.x, DBeaver a HeidiSQL zvládají nový plugin v aktuálních verzích; potíže dělají kopie nainstalované před lety a nikdy neaktualizované. Nastavení připojení pro každý z nich najdeš v článku Grafické klienty MySQL.
Přesun účtu pomocí ALTER USER#
Příkaz, který účet přesune, je krátký a potřebuje heslo:
ALTER USER 'app'@'%' IDENTIFIED WITH caching_sha2_password BY 'the-current-or-a-new-password';Uložené hashe obou pluginů jsou různé funkce hesla a hash SHA-1 nejde převést na SHA-256. MySQL neumí přepnout plugin a ponechat starý hash, takže zadáváš heslo - stejné, které aplikace už používá, pokud ho znáš a nechceš měnit konfiguraci, nebo nové. Pokud současné heslo nikdo nezná, je to příležitost vygenerovat pořádné a uložit ho tam, odkud ho aplikace čte.
Tento příkaz nepotřebuje, aby byl nativní plugin zapnutý. Na běžném serveru 8.4, nebo na 9.x po upgradu, může root nativní účet přesunout přímo; účet se do té doby nemůže přihlásit, ale změnit ho jde.
Při přesunu mnoha účtů vygeneruj příkazy a hesla doplň ručně nebo ze svého úložiště tajemství:
SELECT CONCAT('ALTER USER ', QUOTE(user), '@', QUOTE(host), ' IDENTIFIED WITH caching_sha2_password BY ''CHANGE_ME'';') AS stmtFROM mysql.userWHERE plugin = 'mysql_native_password';Po každém z nich ověř výsledek a otestuj přihlášení k tomuto účtu z místa, kde běží aplikace:
SHOW CREATE USER 'app'@'%';$ mysql -h db.example.net -P 3306 -u app -p --ssl-mode=REQUIRED -e "SELECT CURRENT_USER();"Přesun bez odstávky
Změna pluginu a hesla živého účtu je okamžik, kdy běžící instance se starými údaji přestanou být schopné otevírat nová spojení. Stávající spojení zůstanou navázaná, protože autentizace probíhá jen při připojení, ale pool, který spojení obnovuje, selže. U jedné malé aplikace s restartem o pár sekund později je to přijatelné. U čehokoli vytíženějšího existují dvě čisté cesty.
- Druhý účet. Vytvoř
'app2'@'%'scaching_sha2_passworda stejnými oprávněními (příkazy ke zkopírování ti dáSHOW GRANTS FOR 'app'@'%'), přepni na něj konfiguraci aplikace, nasaď, ověř, že se už nikdo nepřipojuje pod starým účtem, a pak proveďDROP USER 'app'@'%'. - Stejný účet, stejné heslo, rychlé nasazení. Když heslo nezměníš, mění se jen plugin. Klienti, kteří
caching_sha2_passworduž podporují, se znovu připojí bez jakékoli změny konfigurace, takže je přesun neviditelný, pokud byl ovladač aktualizován předem.
Funkce dvou hesel (RETAIN CURRENT PASSWORD) tady nepomůže: MySQL ji nepovoluje v ALTER USER, který mění autentizační plugin.
TLS, klíče RSA a selhání prvního přihlášení#
Jakmile jsou účty na caching_sha2_password, zbývající selhání se týkají toho, že plná autentizace potřebuje zabezpečený kanál. Čisté řešení je TLS: MySQL 8.x při prvním startu vygeneruje self-signed certifikát a klientské knihovny ve výchozím stavu TLS zkoušejí (--ssl-mode=PREFERRED). Klient s vypnutým TLS, nebo knihovna, která TLS ve výchozím stavu nepoužívá, sáhne po RSA a někteří odmítnou klíč stáhnout, dokud jim to nepřikážeš.
| Klient | Nastavení, které umožní plnou autentizaci bez TLS |
|---|---|
mysql CLI | --get-server-public-key |
| Connector/J | allowPublicKeyRetrieval=true |
| MySqlConnector (.NET) | AllowPublicKeyRetrieval=true |
Stažení veřejného klíče přes nešifrované spojení je otevřené útoku man-in-the-middle, který podstrčí vlastní klíč, a proto je ve výchozím stavu vypnuté. V privátní síti je to rozumný kompromis; přes internet použij raději TLS a stahování klíče nech vypnuté. URL pro JDBC, které to dělá správně, vypadá takto:
jdbc:mysql://db.example.net:3306/appdb?sslMode=REQUIREDUnix socket se počítá jako zabezpečený, takže místní připojení přes localhost na stejném stroji na to nikdy nenarazí. Vzdálená připojení jsou místo, kde na tom záleží, a síťovou stránku - firewally, adresy bind a kontrolu certifikátů - pokrývá článek Vzdálená připojení k MySQL.
Zapnutí mysql_native_password zpět na 8.4#
Když aplikaci dnes opravit nejde - třeba binárka od dodavatele se starou klientskou knihovnou uvnitř - MySQL 8.4 dovolí plugin znovu načíst. Je to startovací volba serveru:
[mysqld]mysql_native_password=ONForma pro příkazovou řádku je --mysql-native-password=ON, tak se zapisuje na řádku command: v Docker Compose. Restartuj server a ověř, že to zabralo:
SELECT plugin_name, plugin_statusFROM information_schema.pluginsWHERE plugin_name = 'mysql_native_password';Stav ACTIVE znamená, že se účty na starém pluginu mohou znovu přihlásit. Řádek s jiným stavem, nebo žádný řádek, znamená, že se volba nepřečetla - zkontroluj, které konfigurační soubory server skutečně načítá, pomocí mysqld --verbose --help | grep -A1 "Default options".
Dvě pasti tady lidi chytají. První je nastavení z éry 8.0 default_authentication_plugin=mysql_native_password, které nese mnoho starých Compose souborů a úryvků my.cnf. Tato proměnná byla v 8.4 odstraněna a server s ní v konfiguraci odmítne nastartovat a v chybovém logu ohlásí neznámou proměnnou. Smaž ji; pokud opravdu potřebuješ nativní plugin jako výchozí pro nové účty, ekvivalent v 8.4 je authentication_policy, ale důvod vytvářet nové nativní účty na serveru, kde plugin nemá budoucnost, je malý. Druhá past je očekávat, že tato volba bude fungovat na 9.x. Neexistuje tam a neznámá volba brání startu úplně stejně.
U hostované databáze patří konfigurace serveru poskytovateli, takže to, zda to vůbec nastavit můžeš, závisí na něm. Počítej raději s přesunem účtů; zabere to minuty a nepotřebuješ k tomu ničí svolení.
Upgrade z 8.4 na 9.x#
Vydání MySQL 9.x Innovation a příští LTS nativní plugin nemají vůbec. Upgrade s dosud přítomnými nativními účty uspěje - server nastartuje a data jsou v pořádku - ale ty účty jsou nepoužitelné, dokud je někdo nezmění, a chyba je táž Plugin 'mysql_native_password' is not loaded. Pokud je mezi nimi root, musí se ten někdo dostat dovnitř jinou cestou, což je právě scénář restartu s --skip-grant-tables, kterému se chceš vyhnout.
Pořadí je tedy pevné: aktualizuj ovladače, přesuň účty na 8.4, ověř, že dotaz z předchozí sekce nevrací žádné řádky, a teprve potom přemýšlej o 9.x. Pro produkční databázi není důvod Innovation vydání provozovat vůbec; 8.4 je podporovaná ještě roky. Jde o to, že přesun je stejná práce, ať ho uděláš teď, nebo později pod tlakem.
Při přenosu databáze mezi servery logickým dumpem platí totéž pro účty, které s sebou bereš. Příkaz SHOW CREATE USER zkopírovaný ze starého serveru obsahuje IDENTIFIED WITH 'mysql_native_password' AS '*...' a jeho přehrání na 8.4 selže, nebo problém znovu vytvoří. Účty na novém serveru raději založ znovu s caching_sha2_password - přesun MySQL na nového hostitele tímto přesunem provází. Tarify MySQL od RE:NODE běží na 8.4 LTS a účet root, aplikační databáze i aplikační uživatel se generují s aktuálním výchozím pluginem, takže účty, se kterými začínáš, žádný přesun nepotřebují; ty, které přinášíš ze staršího serveru, ho potřebovat mohou.
FAQ#
Je caching_sha2_password pomalejší než mysql_native_password?
Jen při plné autentizaci a znatelně jen u zátěže, která otevírá nové spojení pro každý požadavek s prázdnou cache. Po prvním přihlášení je účet v cache a rychlá autentizace stojí zhruba stejně jako starý plugin. Connection pool, který většina aplikací stejně používá, ten rozdíl odstraní; jak ho dimenzovat, vysvětluje článek Limity připojení a pooling.
Mohu změnit plugin uživatele, aniž bych znal heslo?
Ne. Plugin a hash patří k sobě a MySQL nedokáže odvodit hash SHA-256 z uloženého hashe SHA-1. V témže příkazu ALTER USER musíš nastavit heslo. Pokud je staré heslo ztracené, nastav nové a aktualizuj konfiguraci aplikace.
Proč přihlášení funguje z mého notebooku, ale ze serveru ne?
Obvykle proto, že oba stroje mají jiné klientské knihovny. Notebook má aktuální mysql CLI nebo grafický nástroj; aplikace na serveru používá starý ovladač zapečený v image nebo v lock souboru. Porovnej přesný text chyby s tabulkou výše - řekne ti, zda odmítá server, nebo klient.
Má MariaDB stejnou změnu?
Ne a v tomto ohledu by se neměly zaměňovat. MariaDB pořád používá mysql_native_password a vlastní pluginy a na serveru neimplementuje caching_sha2_password z MySQL. Proto se také klient MySQL 9.x nedokáže přihlásit k mnoha serverům MariaDB: zahodil jediný plugin, který sdílejí.
Potřebuji FLUSH PRIVILEGES po ALTER USER?
Ne. ALTER USER aktualizuje cache oprávnění a autentizace v paměti okamžitě. Spuštění FLUSH PRIVILEGES navíc vyčistí i cache caching_sha2_password, což donutí každý účet projít při dalším přihlášení plnou autentizací - s TLS neškodné, u klientů bez něj zdroj překvapivých selhání.


