在创建MySQL用户时使用%作为主机

时间:2012-05-30 20:34:21

标签: mysql

我的MySQL数据库需要两个用户:appuser和support 其中一位应用程序开发人员坚持要为这些用户创建四个帐户:

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

对于我的生活,我无法弄清楚为什么他认为我们需要这个。不会使用通配符作为主机来处理'localhost'吗?

有什么想法吗?

(在这里使用MySQL 5.5)

6 个答案:

答案 0 :(得分:90)

localhost在MySQL中很特殊,它意味着通过UNIX套接字(或者我认为是Windows上的命名管道)的连接,而不是TCP / IP套接字。使用%作为主机不包含localhost,因此需要明确指定它。

答案 1 :(得分:30)

正如@nos在当前接受的回答这个问题的评论中指出的那样,接受的答案是不正确的。

是的,当通过套接字连接而不是标准TCP / IP连接进行连接时,对用户帐户主机使用%localhost之间存在差异。

主机值%不包括localhost套接字,因此如果要使用该方法进行连接,则必须指定。

答案 2 :(得分:6)

如果您想从localhost连接user@'%',请使用mysql -h192.168.0.1 -uuser -p

答案 3 :(得分:6)

我们来试试吧。

以超级用户身份连接,然后:

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或其他类似命名的I / O管道),请在命令行上运行此命令(使用--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=TCPmysql命令仍会尝试使用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. 通过检查ps faux
  2. 的输出来获取mysql客户端进程的PID
  3. 运行lsof -n -p<yourpid>
  4. 你会看到类似的东西:

    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连接:FAILURE

    案例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 Domain Socket连接。但这在经验上并非如此。 localhost现在仅指Unix Domain Socket,不再匹配127.0.0.1。

    skip-name-resolve已关闭:

    • 使用套接字连接:确定
    • 从127.0.0.1连接:确定

    skip-name-resolve已开启:

    • 使用套接字连接:确定
    • 从127.0.0.1连接:FAILURE

    案例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;
    
    • 使用套接字连接:确定
    • 从127.0.0.1连接:确定

    (根据MySQL 5.7: 6.2.4 Access Control, Stage 1: Connection Verification空字符串''也表示“任何主机”,但在'%'后排序。

    案例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连接:FAILURE

    但是

    • 使用mysql -pbar -ufoo -h192.168.0.1连接:确定(!)

    后者因为这实际上来自192.168.0.1的TCP连接,如lsof所示:

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

    边缘情况A:主机='0.0.0.0'

    update user set host='0.0.0.0' where user='foo';flush privileges;
    
    • 使用套接字连接:FAILURE
    • 从127.0.0.1连接:FAILURE

    边缘情况B:主机='255.255.255.255'

    update user set host='255.255.255.255' where user='foo';flush privileges;
    
    • 使用套接字连接:FAILURE
    • 从127.0.0.1连接:FAILURE

    边缘情况C:主机='127.0.0.2'

    (127.0.0.2是完全有效的环回地址,相当于RFC6890中定义的127.0.0.1)

    update user set host='127.0.0.2' where user='foo';flush privileges;
    
    • 使用套接字连接:FAILURE
    • 从127.0.0.1连接:FAILURE

    有趣的是:

    • mysql -pbar -ufoo -h127.0.0.2127.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;
    

答案 4 :(得分:5)

为目前提供的答案提供略有不同的答案。

如果您的用户表''@'localhost'中有来自localhost的匿名用户的行,那么这将被视为比具有通配符&#d; d host 'user'@'%'的用户更具体。这就是为什么有必要提供'user'@'localhost'

您可以在this page的底部看到更详细的解释。

答案 5 :(得分:4)

百分比符号表示:任何主机,包括远程和本地连接。

localhost只允许本地连接。

(所以首先,如果您不需要远程连接到您的数据库,您可以立即删除appuser @&#39;%&#39;用户)

所以,是的,它们是重叠的,但是......

...有一个设置两种类型帐户的原因,这在mysql文档中有解释: http://dev.mysql.com/doc/refman/5.7/en/adding-users.html

如果您的localhost上有一个匿名用户,您可以使用该用户:

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

如果您只是创建用户appuser @&#39;%&#39; (而不是appuser @&#39; localhost&#39;),然后是appuser mysql用户 从本地主机连接,使用匿名用户帐户(它优先于您的appuser @&#39;%&#39;用户)。

对此的修复是(可以猜测)创建appuser @&#39; localhost&#39; (更具体地说,本地主机匿名用户,如果您的appuser从localhost连接,将使用它。)