107 votes

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

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

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

Je n'arrive pas à comprendre pourquoi il pense qu'on a besoin de ça. L'utilisation d'un caractère générique comme hôte ne devrait-elle pas prendre en charge le "localhost" ?

Des idées ?

(En utilisant MySQL 5.5 ici)

124voto

aleroot Points 30853

localhost est spécial dans MySQL, cela signifie une connexion sur un socket UNIX (ou des pipes nommés sous Windows, je crois) par opposition à un socket TCP/IP. Utilisation de % car l'hôte ne comprend pas localhost d'où la nécessité de le spécifier explicitement.

35voto

John Kary Points 2020

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 y a une différence entre utiliser % y localhost pour l'hôte du compte utilisateur lors d'une connexion via un socket connect au lieu d'une connexion TCP/IP standard.

Une valeur hôte de % ne comprend pas localhost pour les sockets et doit donc être spécifié si vous voulez vous connecter en utilisant cette méthode.

24voto

David Tonhofer Points 1816

Faisons un test.

Connectez-vous en tant que super-utilisateur, et ensuite :

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

et ensuite

USE mysql;

Configuration

Créer un utilisateur foo avec mot de passe bar pour les tests :

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

Connectez-vous à

Pour se connecter à l'Unix Domain Socket (c'est-à-dire le tuyau d'E/S qui est nommé par l'entrée du système de fichier /var/run/mysqld/mysqld.sock ou autre), exécutez-la en ligne de commande (utilisez la commande --protocol option pour être doublement sûr)

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

On s'attend à ce que le texte ci-dessus corresponde à "user comes from localhost" mais certainement pas à "user comes from 127.0.0.1".

Pour se 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 laissez de côté --protocol=TCP le mysql essaiera toujours d'utiliser le socket du 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 en 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 de sorte qu'il soit transmis à l'utilisateur. mysql processus)

Vérification en cas de doute

Pour vérifier réellement si la connexion passe par un socket TCP/IP ou un socket de domaine Unix

  1. obtenir le PID du processus client mysql en examinant la sortie de ps faux
  2. exécuter 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)

o

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

Donc :

Cas 0 : Hôte = '10.10.10.10' (test nul)

update user set host='10.10.10.10' where user='foo'; flush privileges;
  • Connectez en utilisant la prise : ÉCHEC
  • Connexion depuis 127.0.0.1 : ÉCHEC

Cas 1 : Host = '%'

update user set host='%' where user='foo'; flush privileges;
  • Connectez-vous en utilisant la prise : OK
  • Connexion depuis 127.0.0.1 : OK

Cas 2 : Hôte = 'localhost'.

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

Le comportement varie et cela dépend apparemment de skip-name-resolve . Si cette option est activée, les lignes avec localhost à ignorer selon le protocole. Voici ce que l'on peut lire dans le journal des erreurs : "L'entrée 'utilisateur' 'Root@localhost' est ignorée en mode --skip-name-resolve". . Cela signifie qu'il n'est pas possible de se connecter par l'intermédiaire de Unix Domain Socket. Mais ce n'est pas le cas de manière empirique. localhost signifie désormais UNIQUEMENT le Socket du domaine Unix, et ne correspond plus à 127.0.0.1.

skip-name-resolve est éteint :

  • Connecter en utilisant la prise : OK
  • Connexion depuis 127.0.0.1 : OK

skip-name-resolve est en cours :

  • Connecter en utilisant la prise : OK
  • Connexion depuis 127.0.0.1 : ÉCHEC

Cas 3 : Hôte = '127.0.0.1'.

update user set host='127.0.0.1' where user='foo';flush privileges;
  • Connectez en utilisant la prise : ÉCHEC
  • Connexion depuis 127.0.0.1 : OK

Cas 4 : Hôte = ''

update user set host='' where user='foo';flush privileges;
  • Connecter en utilisant la prise : OK
  • Connexion depuis 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 elle est triée 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-la en conséquence dans votre cas)

update user set host='192.168.0.1' where user='foo';flush privileges;
  • Connectez en utilisant la prise : ÉCHEC
  • Connexion depuis 127.0.0.1 : ÉCHEC

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 de 192.168.0.1 comme l'a révélé lsof :

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

Cas limite 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 : ÉCHEC
  • Connexion depuis 127.0.0.1 : ÉCHEC

Cas limite 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 : ÉCHEC
  • Connexion depuis 127.0.0.1 : ÉCHEC

Cas limite 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 le document RFC6890 )

update user set host='127.0.0.2' where user='foo';flush privileges;
  • Connectez en utilisant la prise : ÉCHEC
  • Connexion depuis 127.0.0.1 : ÉCHEC

C'est intéressant :

  • mysql -pbar -ufoo -h127.0.0.2 se connecte à partir de 127.0.0.1 et c'est l'ÉCHEC
  • mysql -pbar -ufoo -h127.0.0.2 --bind-address=127.0.0.2 est OK

Nettoyage

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

Addendum

Pour voir ce qui se trouve réellement dans le mysql.user qui est l'une des tables de permission, utiliser :

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;

9voto

alex Points 99

Si vous voulez vous connecter à user@'%' à partir de l'hôte local, utilisez mysql -h192.168.0.1 -uuser -p .

9voto

ling Points 177

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

Le localhost 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)

Donc, oui, ils se chevauchent, mais...

...il y a une raison de 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 localhost, 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 non l'appuser@'localhost'), alors lorsque l'utilisateur appuser mysql se connecte depuis l'hôte local, le compte d'utilisateur anonyme est utilisé (il a la priorité sur votre utilisateur appuser@ '%').

Et la solution 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 depuis l'hôte local).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X