Использование% для хоста при создании пользователя MySQL

93

Моей базе данных MySQL нужны два пользователя: appuser и support.
Один из разработчиков приложения настаивает, чтобы я создал четыре учетных записи для этих пользователей:

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.
Phillipp
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

Можно ожидать, что указанное выше соответствует «пользователь исходит из локального хоста», но уж точно не «пользователь приходит с 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

  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;
  • Подключить через разъем: ОК
  • Подключиться с 127.0.0.1: ОК

Случай 2: Host = 'localhost'

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

Поведение меняется, и это, по-видимому, зависит от skip-name-resolve. Если установлено, то строки с localhostигнорируются в соответствии с журналом. В журнале ошибок можно увидеть следующее: «запись пользователя 'root @ localhost' игнорируется в режиме --skip-name-resolve». . Это означает отсутствие подключения через сокет домена Unix. Но эмпирически это не так. localhostтеперь означает ТОЛЬКО сокет домена Unix и больше не соответствует 127.0.0.1.

skip-name-resolve выключен:

  • Подключить через разъем: ОК
  • Подключиться с 127.0.0.1: ОК

skip-name-resolve горит:

  • Подключить через разъем: ОК
  • Подключиться с 127.0.0.1: ОТКАЗ

Случай 3: Host = '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;
  • Подключить через разъем: ОК
  • Подключиться с 127.0.0.1: ОК

(Согласно MySQL 5.7: 6.2.4 Контроль доступа, Этап 1: Проверка соединения , пустая строка "также означает" любой хост ", но сортируется после"% ". )

Случай 5: Host = '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: ОК (!)

Последнее, потому что на самом деле это TCP-соединение 192.168.0.1, как показано lsof:

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

Пограничный случай A: Host = '0.0.0.0'

update user set host='0.0.0.0' where user='foo';flush privileges;
  • Подключить через разъем: FAILURE
  • Подключиться с 127.0.0.1: ОТКАЗ

Пограничный случай B: Host = '255.255.255.255'

update user set host='255.255.255.255' where user='foo';flush privileges;
  • Подключить через разъем: FAILURE
  • Подключиться с 127.0.0.1: ОТКАЗ

Пограничный случай 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'тогда это будет рассматриваться как более конкретное, чем ваш пользователь с подстановочным знаком host '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).

лин
источник