Błąd MySQL: Odmowa dostępu dla użytkownika „a” @ localhost (przy użyciu hasła: TAK)

22

Używam konta root, które utworzyło konto 'a'@'%'. Ale nie mogę używać konta do łączenia się z serwerem MySQL, gdy podam parametr hosta. Mogę pomyślnie połączyć się bez -hparametru. Zobacz zapis poniżej. Mam nadzieję, że ktoś może mi pomóc to wyjaśnić. Dzięki.

mysql> grant all on *.* to 'a'@'%' identified by a;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a' at line 1
mysql> grant all on *.* to 'a'@'%' identified by 'a';
Query OK, 0 rows affected (0.00 sec)

mysql> show grants for 'a'@'%';
+-----------------------------------------------------------------------------------------------------------+
| Grants for a@%                                                                                            |
+-----------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'a'@'%' IDENTIFIED BY PASSWORD '*667F407DE7C6AD07358FA38DAED7828A72014B4E' |
+-----------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> exit
Bye

[root@localhost ~]# mysql -h localhost -u a -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'a'@'localhost' (using password: YES)
[root@localhost ~]# mysql -h 127.0.0.1 -u a -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'a'@'localhost' (using password: YES)
[root@localhost ~]# mysql -u a -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'a'@'localhost' (using password: YES)
[root@localhost ~]# mysql -u a
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 5.5.17 MySQL Community Server (GPL)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
mysql> status
--------------
mysql  Ver 14.14 Distrib 5.5.17, for Linux (x86_64) using readline 5.1

Connection id:      20
Current database:   
Current user:       a@localhost
SSL:            Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server version:     5.5.17 MySQL Community Server (GPL)
Protocol version:   10
Connection:     Localhost via UNIX socket
Server characterset:    utf8
Db     characterset:    utf8
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:        /var/lib/mysql/mysql.sock
Uptime:         15 days 15 hours 20 min 18 sec

Threads: 1  Questions: 40  Slow queries: 0  Opens: 41  Flush tables: 1  Open tables: 4  Queries per second avg: 0.000
--------------

mysql> 

Edytować:

Tak, MySQL nasłuchuje na porcie 3306.

[root@localhost ~]# nmap localhost

Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2012-01-18 07:35 CST
Interesting ports on localhost.localdomain (127.0.0.1):
Not shown: 1674 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
25/tcp   open  smtp
111/tcp  open  rpcbind
631/tcp  open  ipp
840/tcp  open  unknown
3306/tcp open  mysql

Nmap finished: 1 IP address (1 host up) scanned in 0.064 seconds
[root@localhost ~]# 
Tylko uczeń
źródło
1
Nie jestem specjalistą od MySql, ale widziałem ten problem kilka razy, nie wiem z jakiego powodu, rozwiązaniem była wyraźna definicja hosta oprócz 'a'@'%'. więc pierwsza płyta była 'a'@'%', a druga jest 'a'@'localhost'.
com
czy możesz przetestować to samo z niższą wersją mysql ..?
Abdul Manaf
użyj Cpanel Login Szczegóły Aby się połączyć.
Abu Fahim,
W moim przypadku utworzyłem domyślnie trzy anonimowe konta, usunięcie ich rozwiązałoby ten problem
Joaquín L. Robles

Odpowiedzi:

26

Oto szybka i brudna metoda sprawdzenia, w jaki sposób MySQL wykonuje udane uwierzytelnianie.

Uruchom to zapytanie:

SELECT USER(),CURRENT_USER();

USER () informuje o próbie uwierzytelnienia w mysqld

CURRENT_USER () informuje, w jaki sposób zezwolono Ci na uwierzytelnianie przez mysqld

Czasami USER()i CURRENT_USER()są inne. Jest tak, ponieważ uwierzytelnianie mysql odbywa się według określonego protokołu.

Zgodnie z MySQL 5.0 Certification Study Guide

wprowadź opis zdjęcia tutaj

strony 486,487 zawierają następujące informacje na temat algorytmu uwierzytelniania mysql:

Istnieją dwa etapy kontroli dostępu klienta:

W pierwszym etapie klient próbuje się połączyć, a serwer akceptuje lub odrzuca połączenie. Aby próba się powiodła, niektóre wpisy w tabeli użytkowników muszą być zgodne z hostem, z którym łączy się klient, nazwą użytkownika i hasłem.

W drugim etapie (który występuje tylko wtedy, gdy klient nawiązał już połączenie), serwer sprawdza każde zapytanie otrzymane od klienta, aby sprawdzić, czy klient ma wystarczające uprawnienia do jego wykonania.

Serwer dopasowuje klienta do wpisów w tabelach przydziałów na podstawie hosta, z którym łączy się klient, i użytkownika, którego dostarcza klient. Możliwe jest jednak dopasowanie więcej niż jednego rekordu:

Wartości hosta w tabelach dotacji można określić, ponieważ wzorce zawierają wartości symboli wieloznacznych. Jeśli tabela zawiera wpisy z dotacji myhost.example.com, %.example.com, %.com, i %wszystkie z nich pasuje do klienta, który łączy się z myhost.example.com.

Wzory nie są dozwolone dla wartości użytkownika we wpisach tabeli przyznania, ale nazwa użytkownika może być podana jako pusty ciąg znaków, aby określić użytkownika anonimowego. Pusty ciąg pasuje do dowolnej nazwy użytkownika, a zatem skutecznie działa jako symbol wieloznaczny.

Gdy wartości hosta i użytkownika w więcej niż jednym rekordzie tabeli użytkowników są zgodne z klientem, serwer musi zdecydować, którego użyć. Odbywa się to poprzez sortowanie rekordów według najbardziej określonych wartości kolumny Host i Użytkownik, a następnie wybranie pasującego rekordu, który pojawia się jako pierwszy na posortowanej liście, Sortowanie odbywa się w następujący sposób:

W kolumnie hosta wartości literalne, takie jak localhost, 127.0.0.1i myhost.example.comsortuj przed wartościami takimi, %.example.com które zawierają znaki wzorca. Wartości wzoru są sortowane według ich specyficzności. Na przykład %.example.comjest bardziej szczegółowy niż %.com, który jest bardziej szczegółowy niż %.

W kolumnie Użytkownik niepuste nazwy użytkowników są sortowane przed pustymi nazwami użytkowników. Oznacza to, że użytkownicy nieanonimowi sortują się przed użytkownikami anonimowymi.

Serwer wykonuje to sortowanie po uruchomieniu. Odczytuje tablice przydziałów do pamięci, sortuje je i używa kopii w pamięci do kontroli dostępu.

Na podstawie tego opisu nie musisz martwić się o kolejność tabel mysql.user, ponieważ istnieje w pamięci kopia tabel grantu, które są sortowane jak wspomniano wcześniej.

Jeśli chodzi o sposób logowania, mysql -u adziałało tylko . Wróć i zaloguj się ponownie i uruchom te polecenia

SELECT USER(),CURRENT_USER();
SELECT user,host,password FROM mysql.user;

Upewnij się, że

  • każdy użytkownik ma hasło.
  • nie ma anonimowych użytkowników (gdy użytkownik jest pusty)

To tylko zgadywanie, ale podejrzewam mysql -u a, że łączę się przez localhost, ponieważ gdy nie określono protokołu połączenia, domyślnie jest to połączenie za pomocą pliku gniazda. Może istnieć wpis, mysql.userktóry pozwala na anonimowe połączenie localhost.

Uruchom to zapytanie:

SELECT user,host,password FROM mysql.user WHERE user='' AND host='localhost';

Jeśli wrócisz wiersz bez hasła, to w pełni wyjaśnia, dlaczego mysq -u adziała.

AKTUALIZACJA 19.01.2012 11:12 EDT

Craig Efrein podniósł interesujące pytanie: jeśli w tabeli mysql.user istnieją dwie identyczne nazwy użytkowników, jedna z hasłem, a druga bez, czy to oznacza, że ​​MySQL odmawia uwierzytelnienia, gdy nie używa hasła?

To pytanie stanowi doskonałą odpowiedź na temat uwierzytelniania użytkownika MySQL.

Należy pamiętać, że kluczem podstawowym mysql.user jest host, użytkownik. Brak innych indeksów. Pozwala to na wielokrotne występowanie nazwy użytkownika. Każde wystąpienie może mieć inne hasło lub może nie mieć hasła. Dzięki temu użytkownik „dbuser” może zalogować się lokalnie (dbuser @ localhost) bez hasła i ten sam login użytkownika z innego serwera w obrębie danego bloku sieciowego (dbuser@'10.1.2.20 ') przy użyciu hasła takiego jak „pass1”, a ten użytkownik może się zalogować zdalnie z dowolnego miejsca (dbuser @ '%') za pomocą hasła zdalnego, takiego jak „pass2”.

Biorąc pod uwagę algorytm uwierzytelniania używany przez MySQL, nie ma żadnych ograniczeń dotyczących użytkowników z obecnością lub brakiem hasła.

Oto dlaczego Przewodnik po certyfikacji MySQL 5.0 na str. 6 w punktach końcowych wyjaśnia, jak wyczyścić proces uwierzytelniania:

W systemie Unix MySQL zawiera skrypt mysql_secure_installation, który może wykonać kilka pomocnych operacji związanych z bezpieczeństwem podczas instalacji. Skrypt ma następujące możliwości:

  • Ustaw hasło do kont głównych
  • Usuń wszystkie zdalnie dostępne konta root.
  • Usuń anonimowe konta użytkowników. Zwiększa to bezpieczeństwo, ponieważ zapobiega możliwości łączenia się z serwerem MySQL jako root ze zdalnego hosta. W rezultacie każdy, kto chce się połączyć jako root, musi najpierw zalogować się na hoście serwera, co stanowi dodatkową barierę przed atakiem.
  • Usuń testową bazę danych (jeśli usuniesz anonimowe konta, możesz również chcieć usunąć testową bazę danych, do której mają dostęp).
RolandoMySQLDBA
źródło
Tak, próbowałem, zwraca wiersz bez hasła. Dziękujemy za doskonałe wyjaśnienie i poleciliśmy książkę certyfikacyjną MySQL.
Tylko uczeń
2
Rolando, jeśli w tabeli mysql.user istnieją dwie identyczne nazwy użytkowników, jedna z hasłem, a druga bez, czy to oznacza, że ​​MySQL odmawia uwierzytelnienia, gdy nie używasz hasła?
Craig Efrein
@Craig - Twoje pytanie jest godne uwagi. Prześlę go do mojej odpowiedzi i tam zaadresuję.
RolandoMySQLDBA
Dziękuję za szczegółową odpowiedź, w moim przypadku w jakiś sposób skonfigurowałem anonimowych użytkowników.
SoWeLie,
@RolandoMySQLDBA, czy wszystkie informacje zawarte w podręczniku do certyfikacji znajdują się już w podręczniku online MySQL?
Pacerier
5

Symbol wieloznaczny hosta „%” nie pasuje do „localhost”. Domyślnie klient mysql będzie próbował połączyć się przez gniazdo, a nie tcp (zwykle w miejscu /var/lib/mysql/mysql.sock).

Możesz zmienić przydział na „@” „localhost” lub zmusić klienta do działania na stosie TCP, np .:

mysql -u a -p --protocol=TCP
atxdba
źródło
Próbowałem, ale wciąż bez powodzenia.
Tylko uczeń
Jak skonfigurować tę opcję, my.cnfaby nie trzeba już było tego parametru?
shgnInc
1
Ty nie. Jeśli nie podasz -h nazwy hosta, zakłada się, że „localhost” oznacza, że ​​szuka gniazda, a nie portu TCP bez flagi protokołu. Możesz ustawić alias powłoki, jeśli masz dość wpisywania wszystkich argumentów.
atxdba
2

Czy sprawdziłeś, czy MySQL faktycznie nasłuchuje na 3306? Uruchom komendę netstat -tlpn i podaj wyniki. Jeśli nie widzisz 3306, to prawdopodobnie nie.

W my.cnf powinieneś sprawdzić, czy --skip-networking jest skomentowany

[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
language        = /usr/share/mysql/English
bind-address    = 65.55.55.2
# skip-networking
Craig Efrein
źródło
Zrobiłem również to samo, co zadane w pytaniu. a także zrobiłeś to, co powiedziałeś w odpowiedzi, ale wciąż jest ten sam problem.
Abdul Manaf
Czy możesz podać wyniki z następującego zapytania: wybierz użytkownika, hosta z mysql.user;
Craig Efrein
Tak, MySQL nasłuchuje na porcie 3306. Zobacz moją edycję.
Tylko uczeń
Możesz także wypróbować mysql -u user -p -h 127.0.0.1. Jeśli to działa, to wierzę, że jego mysql nie wie, jak rozwiązać localhost. Wpis dla localhost, który wskazuje na 127.0.0.1 w pliku / etc / hosts, rozwiąże ten problem.
Craig Efrein
Czy korzystałeś z uprawnień Flush?
Craig Efrein
1

Jak opisano w @atxdba, aby połączyć demona mysql ze zdalnego, który nie łączy się przez gniazdo, musisz połączyć się ze zdalnego za pomocą TCP.

W tym celu należy określić --protocol=TCPdla każdego połączenia. Chociaż możesz ustawić go my.cnfna serwerze:

[client]
protocol=tcp
shgnInc
źródło