Utilisation de% pour l'hôte lors de la création d'un utilisateur MySQL

93

La base de données MySQL a besoin de deux utilisateurs: appuser et support.
L'un des développeurs d'applications insiste pour que je crée quatre comptes pour ces utilisateurs:

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

Pour la vie de moi, je ne peux pas comprendre pourquoi il pense que nous avons besoin de cela. Est-ce que l'utilisation du caractère générique en tant qu'hôte ne prendrait pas en charge le «localhost»?

Des idées?

(Utilisation de MySQL 5.5 ici)

Ed Manet
la source

Réponses:

106

localhostest spécial dans MySQL, cela signifie une connexion sur un socket UNIX (ou des tubes nommés sous Windows, je crois) par opposition à un socket TCP / IP. L'utilisation %comme hôte n'inclut pas localhost, d'où la nécessité de le spécifier explicitement.

aleroot
la source
Dans quelle version? Dans MySQL 5.5.35, "%" correspond également à localhost.
depquid
4
Non seulement "localhost" se connecte via le socket local, mais 127.0.0.1 (qui n'utilise pas le socket) ne correspondra pas à% mais localhost à la place également. J'ai vu cela avec une installation haproxy aujourd'hui.
Phillipp
33

Comme @nos l'a souligné dans les commentaires de la réponse actuellement acceptée à cette question, la réponse acceptée est incorrecte.

Oui, il existe une différence entre l'utilisation %et localhostpour l'hôte du compte utilisateur lors de la connexion via une connexion socket au lieu d'une connexion TCP / IP standard.

Une valeur d'hôte de %n'inclut pas les localhostsockets et doit donc être spécifiée si vous souhaitez vous connecter à l'aide de cette méthode.

John Kary
la source
15

Testons juste.

Connectez-vous en tant que superutilisateur, puis:

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

puis

USE mysql;

Installer

Créez un utilisateur fooavec un mot barde passe pour le test:

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

Relier

Pour vous connecter au socket de domaine Unix (c'est-à-dire le canal d'E / S qui est nommé par l'entrée du système de fichiers /var/run/mysqld/mysqld.sockou quelque chose du genre), exécutez-le sur la ligne de commande (utilisez l' --protocoloption pour vous assurer à deux fois)

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

On s'attend à ce que ce qui précède corresponde à "l'utilisateur vient de localhost" mais certainement pas "l'utilisateur vient de 127.0.0.1".

Pour vous connecter au serveur à partir de "127.0.0.1" à la place, exécutez ceci sur la ligne de commande

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

Si vous oubliez --protocol=TCP, la mysqlcommande essaiera toujours d'utiliser le socket de domaine Unix. Vous pouvez également dire:

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

Les deux tentatives de connexion sur une seule ligne:

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"

(le mot de passe est défini dans l'environnement pour qu'il soit transmis au mysqlprocessus)

Vérification en cas de doute

Pour vraiment vérifier si la connexion passe via une socket TCP / IP ou une socket de domaine Unix

  1. obtenir le PID du processus client mysql en examinant la sortie de ps faux
  2. courir lsof -n -p<yourpid>.

Vous verrez quelque chose comme:

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

ou

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

Donc:

Cas 0: Host = '10 .10.10.10 '(test nul)

update user set host='10.10.10.10' where user='foo'; flush privileges;
  • Connectez en utilisant la prise: FAILURE
  • Connectez-vous à partir de 127.0.0.1: FAILURE

Cas 1: hôte = '%'

update user set host='%' where user='foo'; flush privileges;
  • Se connecter à l'aide de la prise: OK
  • Se connecter à partir de 127.0.0.1: OK

Cas 2: Host = 'localhost'

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

Le comportement varie et cela dépend apparemment de skip-name-resolve. S'il est défini, les lignes avec localhostsont ignorées en fonction du journal. Ce qui suit peut être vu dans le journal des erreurs: "Entrée" utilisateur "" root @ localhost "ignorée en mode --skip-name-resolution." . Cela signifie qu'il n'y a pas de connexion via le socket de domaine Unix. Mais ce n'est empiriquement pas le cas. localhostsignifie maintenant UNIQUEMENT le socket de domaine Unix, et ne correspond plus à 127.0.0.1.

skip-name-resolve est éteint:

  • Se connecter à l'aide de la prise: OK
  • Se connecter à partir de 127.0.0.1: OK

skip-name-resolve est sur:

  • Se connecter à l'aide de la prise: OK
  • Connectez-vous à partir de 127.0.0.1: FAILURE

Cas 3: Host = '127.0.0.1'

update user set host='127.0.0.1' where user='foo';flush privileges;
  • Connectez en utilisant la prise: FAILURE
  • Se connecter à partir de 127.0.0.1: OK

Cas 4: Host = ''

update user set host='' where user='foo';flush privileges;
  • Se connecter à l'aide de la prise: OK
  • Se connecter à partir de 127.0.0.1: OK

(Selon MySQL 5.7: 6.2.4 Contrôle d'accès, Étape 1: Vérification de la connexion , la chaîne vide «» signifie également «n'importe quel hôte» mais trie après «%». )

Cas 5: Host = '192.168.0.1' (test supplémentaire)

('192.168.0.1' est l'une des adresses IP de ma machine, changez de manière appropriée dans votre cas)

update user set host='192.168.0.1' where user='foo';flush privileges;
  • Connectez en utilisant la prise: FAILURE
  • Connectez-vous à partir de 127.0.0.1: FAILURE

mais

  • Connectez-vous en utilisant mysql -pbar -ufoo -h192.168.0.1: OK (!)

Ce dernier parce qu'il s'agit en fait d'une connexion TCP provenant 192.168.0.1, comme le révèle lsof:

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

Cas Edge A: hôte = '0.0.0.0'

update user set host='0.0.0.0' where user='foo';flush privileges;
  • Connectez en utilisant la prise: FAILURE
  • Connectez-vous à partir de 127.0.0.1: FAILURE

Cas Edge B: hôte = '255.255.255.255'

update user set host='255.255.255.255' where user='foo';flush privileges;
  • Connectez en utilisant la prise: FAILURE
  • Connectez-vous à partir de 127.0.0.1: FAILURE

Cas Edge C: hôte = '127.0.0.2'

(127.0.0.2 est une adresse de bouclage parfaitement valide équivalente à 127.0.0.1 telle que définie dans la RFC6890 )

update user set host='127.0.0.2' where user='foo';flush privileges;
  • Connectez en utilisant la prise: FAILURE
  • Connectez-vous à partir de 127.0.0.1: FAILURE

De façon intéressante:

  • mysql -pbar -ufoo -h127.0.0.2se connecte depuis 127.0.0.1et est FAILURE
  • mysql -pbar -ufoo -h127.0.0.2 --bind-address=127.0.0.2 est OK

Nettoyer

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

Addenda

Pour voir ce qui est réellement dans la mysql.usertable, qui est l'une des tables d'autorisations, utilisez:

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;

cela donne:

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

De même pour la table 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
la source
6
Cela nécessite une conclusion qui clarifie ce que le reste de la réponse dit réellement sans avoir besoin de comprendre le code.
Prometheus
7

Si vous souhaitez vous connecter à user@'%'partir de localhost, utilisez mysql -h192.168.0.1 -uuser -p.

Alex
la source
5

Va fournir une réponse légèrement différente de celles fournies jusqu'à présent.

Si vous avez une ligne pour un utilisateur anonyme de localhost dans votre table users, ''@'localhost'cela sera traité comme plus spécifique que votre utilisateur avec un hôte générique 'user'@'%'. C'est pourquoi il est nécessaire de prévoir également 'user'@'localhost'.

Vous pouvez voir cela expliqué plus en détail au bas de cette page .

Joshua Walsh
la source
5

Le symbole de pourcentage signifie: tout hôte, y compris les connexions distantes et locales.

L'hôte local n'autorise que les connexions locales.

(donc pour commencer, si vous n'avez pas besoin de connexions à distance à votre base de données, vous pouvez vous débarrasser de l'utilisateur appuser @ '%' tout de suite)

Alors, oui, ils se chevauchent, mais ...

... il y a une raison pour définir les deux types de comptes, cela est expliqué dans la documentation mysql: http://dev.mysql.com/doc/refman/5.7/en/adding-users.html .

Si vous avez un utilisateur anonyme sur votre hôte local, que vous pouvez repérer avec:

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

et si vous créez simplement l'utilisateur appuser @ '%' (et vous pas l'appuser @ 'localhost'), alors lorsque l'utilisateur appuser mysql se connecte à partir de l'hôte local, le compte utilisateur anonyme est utilisé (il a priorité sur votre appuser @ utilisateur '%').

Et le correctif pour cela est (comme on peut le deviner) de créer l'appuser @ 'localhost' (qui est plus spécifique que l'utilisateur anonyme de l'hôte local et sera utilisé si votre appuser se connecte à partir de l'hôte local).

lingue
la source