Usando% para el host al crear un usuario de MySQL

93

Mi base de datos MySQL necesita dos usuarios: appuser y support.
Uno de los desarrolladores de aplicaciones insiste en que cree cuatro cuentas para estos usuarios:

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

Por mi vida, no puedo entender por qué cree que necesitamos esto. ¿Usar el comodín como anfitrión no se ocuparía del 'localhost'?

¿Algunas ideas?

(Usando MySQL 5.5 aquí)

Ed Manet
fuente

Respuestas:

106

localhostes especial en MySQL, significa una conexión a través de un socket UNIX (o canalizaciones con nombre en Windows, creo) en lugar de un socket TCP / IP. Usar %como host no incluye localhost, de ahí la necesidad de especificarlo explícitamente.

aleroot
fuente
En que version? En MySQL 5.5.35, "%" también coincide con localhost.
depquid
4
No sólo "localhost" se conecta a través del socket local, 127.0.0.1 (que no usa el socket) no coincidirá con%, sino con localhost también. Lo vi con una instalación haproxy hoy.
Phillipp
33

Como @nos señaló en los comentarios de la respuesta actualmente aceptada a esta pregunta, la respuesta aceptada es incorrecta.

Sí, existe una diferencia entre usar %y localhostpara el host de la cuenta de usuario cuando se conecta a través de una conexión de socket en lugar de una conexión TCP / IP estándar.

Un valor de host de %no incluye localhostpara sockets y, por lo tanto, debe especificarse si desea conectarse utilizando ese método.

John Kary
fuente
15

Probemos.

Conéctese como superusuario y luego:

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

y entonces

USE mysql;

Preparar

Cree un usuario foocon contraseña barpara realizar pruebas:

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

Conectar

Para conectarse al Unix Domain Socket (es decir, la tubería de E / S que recibe el nombre de la entrada del sistema de archivos /var/run/mysqld/mysqld.socko algo así), ejecútelo en la línea de comando (use la --protocolopción para estar doblemente seguro)

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

Se espera que lo anterior coincida con "el usuario proviene de localhost" pero ciertamente no con "el usuario proviene de 127.0.0.1".

Para conectarse al servidor desde "127.0.0.1" en su lugar, ejecute esto en la línea de comando

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

Si lo omite --protocol=TCP, el mysqlcomando seguirá intentando utilizar el socket de dominio Unix. También puede decir:

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

Los dos intentos de conexión en una línea:

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"

(la contraseña se establece en el entorno para que se pase al mysqlproceso)

Verificación en caso de duda

Para comprobar realmente si la conexión se realiza a través de un socket TCP / IP o un socket de dominio Unix

  1. obtener el PID del proceso del cliente mysql examinando la salida de ps faux
  2. correr lsof -n -p<yourpid>.

Verás algo como:

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

o

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

Entonces:

Caso 0: Host = '10 .10.10.10 '(prueba nula)

update user set host='10.10.10.10' where user='foo'; flush privileges;
  • Conectar usando el enchufe: FALLO
  • Conectarse desde 127.0.0.1: FALLO

Caso 1: Host = '%'

update user set host='%' where user='foo'; flush privileges;
  • Conectar usando el enchufe: OK
  • Conectar desde 127.0.0.1: OK

Caso 2: Host = 'localhost'

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

El comportamiento varía y esto aparentemente depende de skip-name-resolve. Si se establece, hace que las líneas con localhostse ignoren según el registro. Se puede ver lo siguiente en el registro de errores: "La entrada 'usuario' 'root @ localhost' ignorada en el modo --skip-name-resolve". . Esto significa que no hay conexión a través del socket de dominio Unix. Pero este no es el caso empíricamente. localhostahora significa SOLO el socket de dominio Unix, y ya no coincide con 127.0.0.1.

skip-name-resolve esta apagado:

  • Conectar usando el enchufe: OK
  • Conectar desde 127.0.0.1: OK

skip-name-resolve Está encendido:

  • Conectar usando el enchufe: OK
  • Conectarse desde 127.0.0.1: FALLO

Caso 3: Host = '127.0.0.1'

update user set host='127.0.0.1' where user='foo';flush privileges;
  • Conectar usando el enchufe: FALLO
  • Conectar desde 127.0.0.1: OK

Caso 4: Anfitrión = ''

update user set host='' where user='foo';flush privileges;
  • Conectar usando el enchufe: OK
  • Conectar desde 127.0.0.1: OK

(De acuerdo con MySQL 5.7: 6.2.4 Control de acceso, Etapa 1: Verificación de conexión , la cadena vacía '' también significa "cualquier host", pero se ordena después de '%' ) .

Caso 5: Host = '192.168.0.1' (prueba adicional)

('192.168.0.1' es una de las direcciones IP de mi máquina, cámbiela apropiadamente en su caso)

update user set host='192.168.0.1' where user='foo';flush privileges;
  • Conectar usando el enchufe: FALLO
  • Conectarse desde 127.0.0.1: FALLO

pero

  • Conectarse usando mysql -pbar -ufoo -h192.168.0.1: OK (!)

Esto último porque en realidad proviene de una conexión TCP 192.168.0.1, como lo revela lsof:

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

Caso de borde A: Host = '0.0.0.0'

update user set host='0.0.0.0' where user='foo';flush privileges;
  • Conectar usando el enchufe: FALLO
  • Conectarse desde 127.0.0.1: FALLO

Caso de borde B: Host = '255.255.255.255'

update user set host='255.255.255.255' where user='foo';flush privileges;
  • Conectar usando el enchufe: FALLO
  • Conectarse desde 127.0.0.1: FALLO

Caso de borde C: Host = '127.0.0.2'

(127.0.0.2 es una dirección de loopback perfectamente válida equivalente a 127.0.0.1 como se define en RFC6890 )

update user set host='127.0.0.2' where user='foo';flush privileges;
  • Conectar usando el enchufe: FALLO
  • Conectarse desde 127.0.0.1: FALLO

Curiosamente:

  • mysql -pbar -ufoo -h127.0.0.2se conecta desde 127.0.0.1y es FALLO
  • mysql -pbar -ufoo -h127.0.0.2 --bind-address=127.0.0.2 esta bien

Limpiar

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

Apéndice

Para ver qué hay realmente en la mysql.usertabla, que es una de las tablas de permisos, use:

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;

esto da:

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

De manera similar para la mesa 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;
David Tonhofer
fuente
6
Esto necesita una conclusión que deje en claro lo que dice el resto de la respuesta sin necesidad de comprender el código.
Prometeo
7

Si desea conectarse user@'%'desde localhost use mysql -h192.168.0.1 -uuser -p.

alex
fuente
5

Vamos a proporcionar una respuesta ligeramente diferente a las proporcionadas hasta ahora.

Si tiene una fila para un usuario anónimo de localhost en su tabla de usuarios ''@'localhost', esto se tratará como más específico que su usuario con host con comodines 'user'@'%'. Por eso es necesario proporcionar también 'user'@'localhost'.

Puede ver esto explicado con más detalle en la parte inferior de esta página .

Joshua Walsh
fuente
5

El símbolo de porcentaje significa: cualquier host, incluidas las conexiones remotas y locales.

El localhost solo permite conexiones locales.

(para empezar, si no necesita conexiones remotas a su base de datos, puede deshacerse del usuario appuser @ '%' de inmediato)

Entonces, sí, se superponen, pero ...

... hay una razón para configurar ambos tipos de cuentas, esto se explica en los documentos de mysql: http://dev.mysql.com/doc/refman/5.7/en/adding-users.html .

Si tiene un usuario anónimo en su localhost, puede detectarlo con:

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

y si solo crea el usuario appuser @ '%' (y no el appuser @ 'localhost'), cuando el usuario appuser mysql se conecta desde el host local, se usa la cuenta de usuario anónimo (tiene prioridad sobre su appuser @ '%' usuario).

Y la solución para esto es (como se puede adivinar) crear el appuser @ 'localhost' (que es más específico que el usuario anónimo del host local y se usará si su appuser se conecta desde el localhost).

abadejo
fuente