MySQL ERROR 1045 (28000): Access denied for user izskatās pēc nepareizas paroles, un dažreiz tā arī ir. Biežāk parole ir pareiza, bet MySQL to salīdzina ar citu kontu, nekā domājat. MySQL konts ir lietotāja vārds un hosts, un serveris izvēlas vienu atbilstošu rindu, pirms vispār skatās uz paroli. Uzziniet, kuru rindu tas izvēlējās, un kļūda parasti kļūst skaidra.
Ziņojumā ir trīs daļas, kuras vērts izlasīt:
ERROR 1045 (28000): Access denied for user 'app'@'10.20.0.15' (using password: YES)
- 'app': lietotāja vārds, ko nosūtīja klients. Ja
-unenorādījāt, MySQL dokumentācija par pieslēgšanos norāda, ka noklusējums ir jūsu Unix lietotāja vārds, tāpēc, palaižotmysqlkā root Linux sistēmā, tiek mēģināts MySQL lietotājsroot. - '10.20.0.15': klienta hosts tā, kā to redz serveris, t.i., IP adrese, atrisināts hosta vārds vai
localhost. Aiz starpniekservera, NAT vai konteineru tīkla tā bieži nav tā mašīna, uz kuras domājat, ka atrodaties. - using password: YES / NO: vai klients vispār nosūtīja paroli. "NO" nozīmē, ka klients paroli nenosūtīja, un parasti tas ir aizmirsts
-p, tukšs mainīgais lietotnes konfigurācijā vai klients, kas lasa nepareizu opciju failu.
Problēmu novēršanas nodaļa to formulē tāpat: ziņojums pasaka, ar kādu lietotāju mēģinājāt ielogoties, no kura hosta un vai izmantojāt paroli. Parasti tabulā mysql.user jābūt vienai rindai, kas precīzi atbilst šim lietotājam un hostam.
Kā MySQL izvēlas kontu
Savienojuma pārbaudes dokumentācija apraksta piekļuves kontroles 1. posmu. Serveris pieņem savienojumu tikai tad, ja klienta hosts un lietotāja vārds atbilst kādas mysql.user rindas kolonnām Host un User, klients uzrāda šīs rindas prasītos akreditācijas datus (tos pārbauda spraudnis no kolonnas plugin) un konts nav bloķēts.
Ja var sakrist vairākas rindas, MySQL nemēģina tās pēc kārtas, līdz parole der. Tas sakārto rindas, ielādējot privilēģiju tabulas, ņem pirmo atbilstošo un salīdzina paroli tikai ar to. Kārtošana liek visspecifiskākos hostus pirmos:
- konkrētas IP adreses un hostu vārdi;
- pēc tam IP diapazoni CIDR pierakstā, tad diapazoni ar tīkla masku;
'%'(jebkurš hosts) tuvu beigām, un tukšs hosts pēc tā.
Viena hosta ietvaros nosaukts lietotājs tiek kārtots pirms anonīmā lietotāja ''. Rindu ar vienādi specifisku hostu un lietotāju secība nav noteikta.
Šī kārtošana ir šīs kļūdas mulsinošākā varianta pamatā. Jūs izveidojat 'app'@'%', testējat no paša datubāzes servera un saņemat "Access denied" ar tikko iestatītu paroli. Dokumentācija izskata tieši šo gadījumu: ja eksistē anonīms konts ''@'localhost', lokālam savienojumam tas ir specifiskāks par '%', tāpēc uzvar. Serveris tad salīdzina jūsu paroli ar anonīmo kontu, un tas neizdodas. Pārliecību, ka vienmēr vispirms tiek pārbaudītas rindas ar jūsu lietotāja vārdu, pati MySQL rokasgrāmata sauc par "izplatītu maldīgu priekšstatu".
Tīra MySQL 8.4 inicializācija izveido 'root'@'localhost' un dažus rezervētos kontus, nevis anonīmus. Vecākās instalācijās un ar roku veidotos serveros tie joprojām var būt, tāpēc pārbaudiet:
SELECT user, host, plugin, account_locked, password_expired
FROM mysql.user
WHERE user IN ('app', '')
ORDER BY host, user;
Ja vispār varat ielogoties, kaut vai kā cits lietotājs, pajautājiet serverim, par ko tas jūs uzskata:
SELECT USER(), CURRENT_USER();
USER() ir tas, ko pieprasīja klients. CURRENT_USER() ir konta rinda, kas tika faktiski izmantota. Ja otrais rāda @localhost ar tukšu lietotāja vārdu, jūs tiekat uzskatīts par anonīmo lietotāju.
localhost nav 127.0.0.1
Unix sistēmās localhost MySQL klientiem ir īpašs: tie pieslēdzas caur Unix soketa failu, nevis TCP/IP. Dokumentācija soketa, named pipe un koplietojamās atmiņas savienojumus uzskata par lokāliem savienojumiem. Tie atbilst hosta daļai localhost, ja tādi konti eksistē, citādi hostiem ar aizstājējzīmēm, kas tai atbilst. Savienojums ar 127.0.0.1 ir TCP/IP un tiek salīdzināts pēc adreses. Tātad vienam lietotājam var būt divi dažādi konti, 'app'@'localhost' un 'app'@'127.0.0.1', ar atšķirīgām parolēm un privilēģijām. Tad "no čaulas strādā, bet no lietotnes ne" ir tieši tas, ko varētu sagaidīt.
mysql -u app -p -h localhost # Unix sokets, atbilst 'app'@'localhost'
mysql -u app -p -h 127.0.0.1 # TCP/IP, salīdzina pēc adreses
mysql -u app -p --protocol=TCP # TCP/IP arī localhost gadījumā
mysql --no-defaults -u app -p -h 127.0.0.1 # neņemt vērā opciju failus
Pēdējā rinda ir svarīgāka, nekā šķiet. Klienti lasa opciju failus, un problēmu novēršanas dokumentācija brīdina, ka veca parole failā ~/.my.cnf vai citā opciju failā rada "Access denied" pat tad, ja paroli neierakstījāt. Ja redzat "using password: YES", lai gan paroli neievadījāt, to nosūta opciju fails. --no-defaults šo iespēju izslēdz dažās sekundēs.
Vārdu atrisināšana ir otrs hosta puses slazds. Ja kontus izveidojāt ar hostu vārdiem, bet serveris darbojas ar skip_name_resolve, hostu kešatmiņas dokumentācija norāda, ka izmantot var tikai kontus ar IP adresēm (un localhost). Ja DNS uzmeklēšana neizdodas, kļūdā lietotājs var parādīties kā ''@'unknown' vai ar tukšu hostu.
Labojiet ar pareizo kontu, nevis plašāku
Kad zināt, kādu hostu redz serveris un kura rinda sakrita, risinājums parasti ir viens no šiem:
- Šim lietotājam no šī hosta nav rindas. Izveidojiet to reālajam klientu tīklam un piešķiriet tikai nepieciešamās tiesības.
- Uzvar nepareizā rinda. Izdzēsiet anonīmo kontu vai pievienojiet lietotājam specifiskāku kontu. Ja privilēģiju tabulas mainījāt ar tiešiem
INSERT/UPDATE/DELETE, nevisCREATE USERvaiALTER USER, izpildietFLUSH PRIVILEGES. Dokumentācija norāda, ka tiešas izmaiņas nestājas spēkā, kamēr tās netiek pārlādētas. - Divu līdzīgu kontu paroles atšķiras. Atiestatiet paroli tieši tam kontam, kas sakrita, t.i., tam, ko parādīja
CURRENT_USER().
-- atsevišķs konts reālajam klientu tīklam
CREATE USER 'app'@'10.20.0.%' IDENTIFIED BY 'garā-nejaušā-parole';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app'@'10.20.0.%';
-- vai nomainiet paroli tieši tam kontam, kas sakrita
ALTER USER 'app'@'10.20.0.%' IDENTIFIED BY 'garā-nejaušā-parole';
Lietotāju un hostu ielieciet pēdiņās atsevišķi. Kontu nosaukumu dokumentācija norāda, ka 'app@10.20.0.%' vienās pēdiņās ir lietotājs ar burtisku vārdu app@10.20.0.% hostā '%', un šāda uzvedība ir novecojusi.
'app'@'%' ar ALL PRIVILEGES un iet tālāk. Tas padara kontu sasniedzamu no jebkura hosta, kas tiek līdz portam 3306. Turklāt tas var pat neatrisināt problēmu, ja joprojām uzvar specifiskāka rinda. Pati dokumentācija iesaka pagaidu '%' aizstāt ar reālo hostu, tiklīdz tas ir zināms.Līdzīgas kļūdas, kas nav 1045
Servera kļūdu sarakstā ir vairākas līdzīgas kļūdas, kuras viegli sajaukt, un katra norāda uz citu cēloni:
- 1698 "Access denied for user 'root'@'localhost'" bez daļas "using password". 8.4 autentifikācijas pirmkodā šis variants tiek izmantots, kad spraudnis ziņo, ka parole apmaiņā nemaz nepiedalījās, kā tas ir ar auth_socket. Šis spraudnis autentificē soketa klientus pēc operētājsistēmas lietotāja, kas palaidis klientu. Dažas pakotņu instalācijas var šādi iestatīt lokālos administratora kontus. Ja
root@localhostkolonnāpluginirauth_socket, palaidiet klientu kā atbilstošais OS lietotājs. Parole nepalīdzēs. - 1130 "Host '...' is not allowed to connect to this MySQL server": šim hostam nav neviena konta.
- 1044 "Access denied for user ... to database ...": ielogošanās izdevās, bet kontam nav tiesību uz šo datubāzi.
- 3118 "Account is locked" un 3955 "Account is blocked ... due to ... consecutive failed login attempts": konts ir bloķēts ar
ACCOUNT LOCKvai īslaicīgi bloķēts arFAILED_LOGIN_ATTEMPTSunPASSWORD_LOCK_TIME.
Pēc atjauninājumiem vērts pārbaudīt arī autentifikācijas spraudņus. MySQL 8.4 pēc noklusējuma vairs neieslēdz mysql_native_password. Konti, kas joprojām izmanto šo spraudni, pārstāj darboties, kamēr tos nepārceļat vai spraudni neieslēdzat atpakaļ, kā skaidrots mūsu MySQL 8.0 uz 8.4 atjaunināšanas ceļvedī.
Skatiet kļūmes servera žurnālā
Klients saņem tikai īso ziņojumu. Serveris var žurnalēt arī katru noraidīto pieslēgšanos, bet tikai ar augstāko detalizācijas līmeni. 8.4 pirmkodā piekļuves lieguma ieraksti tiek rakstīti ar INFORMATION prioritāti. Sistēmas mainīgo dokumentācija rāda, ka log_error_verbosity noklusējums ir 2 (kļūdas un brīdinājumi), bet 3 pievieno informatīvos ziņojumus. Mainīgais ir dinamisks, tāpēc atkļūdošanas laikā to var uz brīdi paaugstināt:
SET GLOBAL log_error_verbosity = 3;
-- atkārtojiet neveiksmīgo pieslēgšanos un izlasiet kļūdu žurnālu
SET GLOBAL log_error_verbosity = 2;
Pēkšņs šādu ierakstu uzliesmojums no vienas adreses ir jāizpēta. Tā var būt izvietošana ar novecojušu noslēpumu, kas mēģina atkārtoti cilpā. Kamēr to labojat, sekojiet arī savienojumu skaitam: agresīvi atkārtojumi palielina slodzi, un kopā ar citām problēmām tie noslogotu serveri var pietuvināt kļūdai "Too many connections".
Pazaudēta root parole: atiestatiet to droši
Ja nevienam nav strādājoša administratora pieteikšanās, drošākais ceļš ir oficiālā atiestatīšanas procedūra Unix sistēmām. Korekti apturiet serveri un ierakstiet vienu rindu ALTER USER 'root'@'localhost' IDENTIFIED BY '...'; failā, ko var lasīt tikai OS lietotājs mysql. Tad vienreiz palaidiet mysqld ar --init-file, kas norāda uz šo failu. Kad serveris ir startējis, izdzēsiet failu, tad apturiet serveri un restartējiet to normāli.
Vispārīgā alternatīva, --skip-grant-tables, ļauj ikvienam pieslēgties bez paroles un ar visām tiesībām. Dokumentācija norāda, ka šajā režīmā MySQL automātiski ieslēdz skip_networking, lai bloķētu attālos savienojumus. Turklāt pirms kontu komandām, piemēram, ALTER USER, jāizpilda FLUSH PRIVILEGES. Izmantojiet to tikai tad, ja init-file metode nav iespējama, turiet šo logu īsu un uzreiz pēc tam restartējiet normāli.
Pēc jaunas instalācijas kļūda 1045 lietotājam root@localhost ar "using password: NO" parasti nozīmē, ka inicializācija ģenerēja nejaušu root paroli. Dokumentācija iesaka to meklēt kļūdu žurnālā.
Galvenās atziņas
- MySQL ERROR 1045 ir par kontu, lietotāju un hostu, kas sakrita pirmais. Ļoti bieži problēma nav parolē.
- Rindas tiek kārtotas pēc hosta specifiskuma, un anonīmais
''@'localhost'var uzvarēt'app'@'%'. localhostnozīmē Unix soketu,127.0.0.1nozīmē TCP. Tie var būt dažādi konti.- Salīdziniet
USER()unCURRENT_USER()un izmantojiet--no-defaults, lai izslēgtu opciju failus. - Kļūdas 1698, 1130, 1044, 3118 un 3955 izskatās līdzīgi, bet to cēloņi ir citi.
- Pazaudētu root paroli atiestatiet ar
--init-file, un jebkuru--skip-grant-tableslogu turiet īsu.