Używanie% dla hosta podczas tworzenia użytkownika MySQL


93

Baza danych MySQL potrzebuje dwóch użytkowników: appuser i support.
Jeden z twórców aplikacji nalega, abym utworzył cztery konta dla tych użytkowników:

appuser@'%'
appuser@'localhost'
support@'%'
support@'localhost'

Na całe życie nie mogę zrozumieć, dlaczego sądzi, że tego potrzebujemy. Czy użycie symbolu wieloznacznego jako hosta nie zajmie się „hostem lokalnym”?

Jakieś pomysły?

(Używając MySQL 5.5 tutaj)

Odpowiedzi:


106

localhostjest wyjątkowy w MySQL, oznacza połączenie przez gniazdo UNIX (lub, jak sądzę, nazwane potoki w systemie Windows) w przeciwieństwie do gniazda TCP / IP. Używanie %jako hosta nie obejmuje localhost, stąd potrzeba jawnego określenia tego.


W jakiej wersji? W MySQL 5.5.35 „%” pasuje również do localhost.
depquid

4
Nie tylko "localhost" łączy się przez lokalne gniazdo, 127.0.0.1 (które nie używa gniazda) nie będzie pasować do%, ale zamiast tego również localhost. Widziałem to z haproxy dzisiaj.
Phillipp,

33

Jak @nos zauważył w komentarzach do aktualnie zaakceptowanej odpowiedzi na to pytanie, przyjęta odpowiedź jest nieprawidłowa.

Tak, istnieje różnica między korzystaniem z hosta konta użytkownika %a korzystaniem localhostz hosta konta użytkownika w przypadku łączenia się przez gniazdo zamiast standardowego połączenia TCP / IP.

Wartość hosta %nie obejmuje localhostgniazd i dlatego musi zostać określona, ​​jeśli chcesz łączyć się przy użyciu tej metody.


15

Po prostu przetestujmy.

Połącz się jako superużytkownik, a następnie:

SHOW VARIABLES LIKE "%version%"; 
+-------------------------+------------------------------+ 
| Variable_name           | Value                        | 
+-------------------------+------------------------------+ 
| version                 | 10.0.23-MariaDB-0+deb8u1-log | 

i wtedy

USE mysql;

Ustawiać

Utwórz użytkownika fooz hasłem bardo testowania:

CREATE USER foo@'%' IDENTIFIED BY 'bar'; FLUSH PRIVILEGES;

Połączyć

Aby połączyć się z Unix Domain Socket (tj. Potokiem I / O, który jest nazwany przez wpis systemu plików /var/run/mysqld/mysqld.socklub coś podobnego), uruchom to w wierszu poleceń (użyj --protocolopcji, aby upewnić się podwójnie)

mysql -pbar -ufoo
mysql -pbar -ufoo --protocol=SOCKET

Można się spodziewać, że powyższe dopasowanie „użytkownik pochodzi z hosta lokalnego”, ale z pewnością nie „użytkownik pochodzi z 127.0.0.1”.

Aby zamiast tego połączyć się z serwerem z „127.0.0.1”, uruchom to w wierszu poleceń

mysql -pbar -ufoo --bind-address=127.0.0.1 --protocol=TCP

Jeśli pominiesz --protocol=TCP, mysqlpolecenie nadal będzie próbowało użyć gniazda domeny Unix. Możesz też powiedzieć:

mysql -pbar -ufoo --bind-address=127.0.0.1 --host=127.0.0.1

Dwie próby połączenia w jednej linii:

export MYSQL_PWD=bar; \
mysql -ufoo --protocol=SOCKET --execute="SELECT 1"; \
mysql -ufoo --bind-address=127.0.0.1 --host=127.0.0.1 --execute="SELECT 1"

(hasło jest ustawione w środowisku, tak aby było przekazywane do mysql procesu)

Weryfikacja w przypadku wątpliwości

Aby naprawdę sprawdzić, czy połączenie przechodzi przez gniazdo TCP / IP lub gniazdo domeny Unix

  1. pobierz PID procesu klienta mysql, sprawdzając dane wyjściowe ps faux
  2. biegać lsof -n -p<yourpid>.

Zobaczysz coś takiego:

mysql [PID] quux 3u IPv4 [code] 0t0 TCP 127.0.0.1:[port]->127.0.0.1:mysql (ESTABLISHED)

lub

mysql [PID] quux 3u unix [code] 0t0 [code] socket

Więc:

Przypadek 0: Host = „10 .10.10.10” (test zerowy)

update user set host='10.10.10.10' where user='foo'; flush privileges;
  • Podłącz za pomocą gniazda: FAILURE
  • Połącz z 127.0.0.1: FAILURE

Przypadek 1: Host = „%”

update user set host='%' where user='foo'; flush privileges;
  • Podłącz za pomocą gniazda: OK
  • Połącz z 127.0.0.1: OK

Przypadek 2: Host = 'localhost'

update user set host='localhost' where user='foo';flush privileges;

Zachowanie jest różne i najwyraźniej zależy od tego skip-name-resolve. Jeśli jest ustawiona, powoduje localhostignorowanie wierszy z zgodnie z dziennikiem. W dzienniku błędów można zobaczyć następujące informacje: „Wpis„ użytkownika ”„ root @ localhost ”został zignorowany w trybie --skip-name-solution.” . Oznacza to brak łączenia się przez gniazdo domeny Unix. Ale empirycznie tak nie jest.localhostteraz oznacza TYLKO Unix Domain Socket i już nie pasuje do 127.0.0.1.

skip-name-resolve jest wyłączony:

  • Podłącz za pomocą gniazda: OK
  • Połącz z 127.0.0.1: OK

skip-name-resolve jest włączony:

  • Podłącz za pomocą gniazda: OK
  • Połącz z 127.0.0.1: FAILURE

Przypadek 3: Host = „127.0.0.1”

update user set host='127.0.0.1' where user='foo';flush privileges;
  • Podłącz za pomocą gniazda: FAILURE
  • Połącz z 127.0.0.1: OK

Przypadek 4: Host = ''

update user set host='' where user='foo';flush privileges;
  • Podłącz za pomocą gniazda: OK
  • Połącz z 127.0.0.1: OK

(Zgodnie z MySQL 5.7: 6.2.4 Kontrola dostępu, etap 1: weryfikacja połączenia , pusty ciąg „” oznacza również „dowolny host”, ale sortuje po „%” ).

Przypadek 5: Host = „192.168.0.1” (dodatkowy test)

(„192.168.0.1” to jeden z adresów IP mojego komputera, zmień odpowiednio w swoim przypadku)

update user set host='192.168.0.1' where user='foo';flush privileges;
  • Podłącz za pomocą gniazda: FAILURE
  • Połącz z 127.0.0.1: FAILURE

ale

  • Połącz za pomocą mysql -pbar -ufoo -h192.168.0.1: OK (!)

To drugie, ponieważ jest to w rzeczywistości połączenie TCP 192.168.0.1, jak ujawniono lsof:

TCP 192.168.0.1:37059->192.168.0.1:mysql (ESTABLISHED)

Przypadek skrajny A: Host = „0.0.0.0”

update user set host='0.0.0.0' where user='foo';flush privileges;
  • Podłącz za pomocą gniazda: FAILURE
  • Połącz z 127.0.0.1: FAILURE

Przypadek krawędzi B: Host = „255.255.255.255”

update user set host='255.255.255.255' where user='foo';flush privileges;
  • Podłącz za pomocą gniazda: FAILURE
  • Połącz z 127.0.0.1: FAILURE

Edge Case C: Host = „127.0.0.2”

(127.0.0.2 to doskonale poprawny adres sprzężenia zwrotnego odpowiadający 127.0.0.1 zdefiniowanemu w RFC6890 )

update user set host='127.0.0.2' where user='foo';flush privileges;
  • Podłącz za pomocą gniazda: FAILURE
  • Połącz z 127.0.0.1: FAILURE

Co ciekawe:

  • mysql -pbar -ufoo -h127.0.0.2łączy się z 127.0.0.1i jest FAILURE
  • mysql -pbar -ufoo -h127.0.0.2 --bind-address=127.0.0.2 jest OK

Sprzątać

delete from user where user='foo';flush privileges;

Uzupełnienie

Aby zobaczyć, co faktycznie znajduje się w mysql.usertabeli, która jest jedną z tabel uprawnień, użyj:

SELECT SUBSTR(password,1,6) as password, user, host,
Super_priv AS su,
Grant_priv as gr,
CONCAT(Select_priv, Lock_tables_priv) AS selock,
CONCAT(Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv) AS modif,
CONCAT(References_priv, Index_priv, Alter_priv) AS ria,
CONCAT(Create_tmp_table_priv, Create_view_priv, Show_view_priv) AS views,
CONCAT(Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) AS funcs,
CONCAT(Repl_slave_priv, Repl_client_priv) AS replic,
CONCAT(Shutdown_priv, Process_priv, File_priv, Show_db_priv, Reload_priv, Create_user_priv) AS admin
FROM user ORDER BY user, host;

to daje:

+----------+----------+-----------+----+----+--------+-------+-----+-------+-------+--------+--------+
    | password | user     | host      | su | gr | selock | modif | ria | views | funcs | replic | admin  |
    +----------+----------+-----------+----+----+--------+-------+-----+-------+-------+--------+--------+
    | *E8D46   | foo      |           | N  | N  | NN     | NNNNN | NNN | NNN   | NNNNN | NN     | NNNNNN |

Podobnie dla tabeli mysql.db:

SELECT host,db,user, 
       Grant_priv as gr,
       CONCAT(Select_priv, Lock_tables_priv) AS selock, 
       CONCAT(Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv) AS modif, 
       CONCAT(References_priv, Index_priv, Alter_priv) AS ria, 
       CONCAT(Create_tmp_table_priv, Create_view_priv, Show_view_priv) AS views, 
       CONCAT(Create_routine_priv, Alter_routine_priv, Execute_priv) AS funcs 
       FROM db ORDER BY user, db, host;

6
Wymaga to wniosku, który wyjaśnia, co tak naprawdę mówi reszta odpowiedzi, bez konieczności rozumienia kodu.
Prometeusz

7

Jeśli chcesz połączyć się user@'%'z localhost użyj mysql -h192.168.0.1 -uuser -p.


5

Zamierzam udzielić nieco innej odpowiedzi niż dotychczas.

Jeśli masz wiersz dla anonimowego użytkownika z hosta lokalnego w tabeli użytkowników, ''@'localhost'będzie to traktowane jako bardziej szczegółowe niż twój użytkownik z hostem z symbolem wieloznacznym 'user'@'%'. Dlatego konieczne jest również zapewnienie 'user'@'localhost'.

Możesz zobaczyć to wyjaśnione bardziej szczegółowo na dole tej strony .


5

Symbol procentu oznacza: dowolny host, w tym połączenia zdalne i lokalne.

Lokalny host zezwala tylko na połączenia lokalne.

(więc na początek, jeśli nie potrzebujesz zdalnych połączeń z bazą danych, możesz od razu pozbyć się użytkownika appuser @ '%')

Więc tak, pokrywają się, ale ...

... istnieje powód dla ustawienia obu typów kont, jest to wyjaśnione w dokumentacji mysql: http://dev.mysql.com/doc/refman/5.7/en/adding-users.html .

Jeśli masz anonimowego użytkownika na swoim hoście lokalnym, którego możesz rozpoznać za pomocą:

select Host from mysql.user where User='' and Host='localhost';

a jeśli po prostu utworzysz appuser użytkownika @ '%' (a nie jesteś appuser @ 'localhost'), to gdy użytkownik appuser mysql łączy się z lokalnego hosta, używane jest konto anonimowego użytkownika (ma pierwszeństwo przed twoim appuser @ „%” użytkownika).

Rozwiązaniem tego problemu jest (jak można się domyślić) utworzenie appuser @ 'localhost' (co jest bardziej szczegółowe niż anonimowy użytkownik lokalnego hosta i będzie używany, jeśli appuser połączy się z localhost).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.