Використання% для хоста при створенні користувача MySQL


93

Базі даних MySQL потрібні два користувачі: appuser та підтримка.
Один із розробників додатків наполягає на тому, щоб я створив чотири облікові записи для цих користувачів:

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

За все життя я не можу зрозуміти, чому він вважає, що нам це потрібно. Чи не використовуючи узагальнюючий знак як ведучого подбати про "локального хоста"?

Будь-які ідеї?

(Використання MySQL 5.5 тут)

Відповіді:


106

localhostособливий у MySQL, це означає підключення через сокет UNIX (або, на мою думку, іменовані канали в Windows) на відміну від сокета TCP / IP. Використання %в якості хоста не включає localhost, отже, необхідність чітко його вказати.


В якій версії? У MySQL 5.5.35 "%" також відповідає localhost.
Depquid

4
"Localhost" не тільки підключається через локальний сокет, 127.0.0.1 (який не використовує сокет) не буде відповідати%, але і localhost, натомість. Побачив це за допомогою інсталяції haproxy сьогодні.
Філіпп

33

Як зазначив @nos у коментарях прийнятої на даний момент відповіді на це питання, прийнята відповідь є неправильною.

Так, Є різниця між використанням %і localhostдля хосту облікового запису користувача при підключенні через підключення через сокет замість стандартного підключення TCP / IP.

Значення хоста %не включає localhostдля сокетів, тому його слід вказати, якщо ви хочете підключитися за допомогою цього методу.


15

Давайте просто перевіримо.

Підключіться як суперкористувач, а потім:

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

і потім

USE mysql;

Налаштування

Створіть користувача fooз паролем barдля тестування:

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

Підключіться

Щоб підключитися до доменного сокета Unix (тобто каналу вводу-виводу, який іменований записом файлової системи /var/run/mysqld/mysqld.sockабо якимсь іншим), запустіть це в командному рядку (використовуйте --protocolопцію, щоб подвоїти впевненість)

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

Очікується, що наведене вище збіги "користувач походить з localhost", але, звичайно, не "користувач походить з 127.0.0.1".

Щоб натомість підключитися до сервера із "127.0.0.1", запустіть це в командному рядку

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

Якщо пропустити --protocol=TCP, mysqlкоманда все одно спробує використовувати сокет домену Unix. Ви також можете сказати:

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

Дві спроби з'єднання в один рядок:

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"

(пароль встановлюється в середовищі таким чином, щоб він передавався mysqlпроцесу)

Перевірка у разі сумніву

Щоб реально перевірити, чи з'єднання проходить через сокет TCP / IP або сокет Unix Domain

  1. отримати PID процесу клієнта mysql, вивчивши результати ps faux
  2. бігти lsof -n -p<yourpid>.

Ви побачите щось на зразок:

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

або

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

Тому:

Випадок 0: Хост = '10 .10.10.10 '(нульовий тест)

update user set host='10.10.10.10' where user='foo'; flush privileges;
  • Підключіться за допомогою розетки: FAILURE
  • Підключення з 127.0.0.1: ПОМИЛКА

Випадок 1: Хост = '%'

update user set host='%' where user='foo'; flush privileges;
  • Підключення за допомогою розетки: OK
  • Підключитися з 127.0.0.1: Добре

Випадок 2: Хост = 'localhost'

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

Поведінка різниться, і це, очевидно, залежить від skip-name-resolve. Якщо встановлено, змушує localhostігнорувати рядки з відповідно до журналу. У журналі помилок можна побачити таке: "запис користувача" root @ localhost "ігнорується в режимі --skip-name-resolution." . Це означає відсутність підключення через Unix Domain Socket. Але це емпірично не так. localhostтепер означає ТІЛЬКИ доменне гніздо Unix і більше не відповідає 127.0.0.1.

skip-name-resolve вимкнено:

  • Підключення за допомогою розетки: OK
  • Підключитися з 127.0.0.1: Добре

skip-name-resolve є на:

  • Підключення за допомогою розетки: OK
  • Підключення з 127.0.0.1: ПОМИЛКА

Випадок 3: Хост = '127.0.0.1'

update user set host='127.0.0.1' where user='foo';flush privileges;
  • Підключіться за допомогою розетки: FAILURE
  • Підключитися з 127.0.0.1: Добре

Випадок 4: Хост = ''

update user set host='' where user='foo';flush privileges;
  • Підключення за допомогою розетки: OK
  • Підключитися з 127.0.0.1: Добре

(Відповідно до MySQL 5.7: 6.2.4 Контроль доступу, Етап 1: Перевірка з'єднання , порожній рядок '' також означає "будь-який хост", але сортується після "%". )

Випадок 5: Хост = '192.168.0.1' (додатковий тест)

('192.168.0.1' - це одна з IP-адрес мого комп'ютера, відповідно змініть у вашому випадку)

update user set host='192.168.0.1' where user='foo';flush privileges;
  • Підключіться за допомогою розетки: FAILURE
  • Підключення з 127.0.0.1: ПОМИЛКА

але

  • Підключіться за допомогою mysql -pbar -ufoo -h192.168.0.1: OK (!)

Останнє, оскільки це насправді TCP-з'єднання, що надходить 192.168.0.1, як виявляє lsof:

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

Edge Case A: Host = '0.0.0.0'

update user set host='0.0.0.0' where user='foo';flush privileges;
  • Підключіться за допомогою розетки: FAILURE
  • Підключення з 127.0.0.1: ПОМИЛКА

Edge Case B: Host = '255.255.255.255'

update user set host='255.255.255.255' where user='foo';flush privileges;
  • Підключіться за допомогою розетки: FAILURE
  • Підключення з 127.0.0.1: ПОМИЛКА

Edge Case C: Host = '127.0.0.2'

(127.0.0.2 - це цілком допустима адреса зворотного зв'язку, еквівалентна 127.0.0.1, як визначено у RFC6890 )

update user set host='127.0.0.2' where user='foo';flush privileges;
  • Підключіться за допомогою розетки: FAILURE
  • Підключення з 127.0.0.1: ПОМИЛКА

Цікаво:

  • mysql -pbar -ufoo -h127.0.0.2з'єднується з 127.0.0.1і є ПОМИЛКОЮ
  • mysql -pbar -ufoo -h127.0.0.2 --bind-address=127.0.0.2 це нормально

Прибирати

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

Додаток

Щоб побачити, що насправді є в mysql.userтаблиці, яка є однією з таблиць дозволів, використовуйте:

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;

це дає:

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

Аналогічно для таблиці 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
Для цього потрібен висновок, який дає зрозуміти, що насправді говорить решта відповідей, не потребуючи розуміння коду.
Прометей

7

Якщо ви хочете підключитися до user@'%'локального хосту mysql -h192.168.0.1 -uuser -p.


5

Надамо дещо іншу відповідь на відповіді, подані до цього часу.

Якщо у вашій таблиці користувачів є рядок для анонімного користувача з localhost, ''@'localhost'тоді це буде розглядатися як більш конкретне, ніж ваш користувач із підстановочним хостом 'user'@'%'. Ось чому необхідно також надавати 'user'@'localhost'.

Ви можете побачити це більш докладно внизу цієї сторінки .


5

Символ відсотків означає: будь-який хост, включаючи віддалене та локальне з'єднання.

Localhost дозволяє лише локальні з'єднання.

(отже, для початку, якщо вам не потрібні віддалені підключення до бази даних, ви можете відразу позбутися користувача appuser @ '%')

Так, так, вони перекриваються, але ...

... є причина для встановлення обох типів облікових записів, це пояснюється в документах mysql: http://dev.mysql.com/doc/refman/5.7/en/adding-users.html .

Якщо на вашому локальному хості є анонімний користувач, якого ви можете знайти за допомогою:

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

і якщо ви просто створюєте користувача appuser @ '%' (а ви не appuser @ 'localhost'), тоді, коли користувач appuser mysql підключається з локального хосту, використовується анонімний обліковий запис користувача (він має перевагу над вашим appuser @ користувач '%').

І виправленням цього є (як можна здогадатися) створення appuser @ 'localhost' (що є більш конкретним, ніж анонімний користувач локального хосту і буде використовуватися, якщо ваш appuser підключається від localhost).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.