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


93

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

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

对于我的一生,我不知道他为什么认为我们需要这个。不会使用通配符作为主机来处理“本地主机”吗?

有任何想法吗?

(在这里使用MySQL 5.5)

Answers:


106

localhostMySQL在MySQL中是特殊的,它表示通过UNIX套接字(我相信Windows上是命名管道)的连接,而不是TCP / IP套接字。使用%如主机不包含localhost,因此需要明确的指定。


什么版本?在MySQL 5.5.35中,“%”也匹配localhost。
2014年

4
不仅“本地主机”通过本地套接字连接,127.0.0.1(不使用该套接字)将不匹配%,但是本地主机也将不匹配。今天通过haproxy安装看到了这一点。
菲利普2014年

33

正如@nos在此问题的当前接受答案的注释中指出的那样,接受的答案不正确。

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

主机的值%不包含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或类似名称命名的I / O管道),请在命令行上运行此命令(使用该--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. 通过检查的输出来获取mysql客户端进程的PID 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;
  • 使用插座连接:失败
  • 从127.0.0.1连接:失败

情况1:主机='%'

update user set host='%' where user='foo'; flush privileges;
  • 使用插座连接:确定
  • 从127.0.0.1连接:确定

情况2:主机='localhost'

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

行为各不相同,这显然取决于skip-name-resolve。如果设置,将导致localhost根据日志忽略行。在错误日志中可以看到以下内容:“在--skip-name-resolve模式下忽略了'user'条目'root @ localhost'。。这意味着没有通过Unix域套接字的连接。但这不是事实。localhost现在仅表示Unix域套接字,并且不再匹配127.0.0.1。

skip-name-resolve 已关闭:

  • 使用插座连接:确定
  • 从127.0.0.1连接:确定

skip-name-resolve 开启:

  • 使用插座连接:确定
  • 从127.0.0.1连接:失败

情况3:主机='127.0.0.1'

update user set host='127.0.0.1' where user='foo';flush privileges;
  • 使用插座连接:失败
  • 从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:主机=“ 192.168.0.1”(额外测试)

(“ 192.168.0.1”是我机器的IP地址之一,请根据您的情况进行相应更改)

update user set host='192.168.0.1' where user='foo';flush privileges;
  • 使用插座连接:失败
  • 从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:主机='0.0.0.0'

update user set host='0.0.0.0' where user='foo';flush privileges;
  • 使用插座连接:失败
  • 从127.0.0.1连接:失败

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

update user set host='255.255.255.255' where user='foo';flush privileges;
  • 使用插座连接:失败
  • 从127.0.0.1连接:失败

边缘情况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;
  • 使用插座连接:失败
  • 从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@'%'要从localhost连接到,请使用mysql -h192.168.0.1 -uuser -p


5

与目前提供的答案稍有不同。

如果您的用户表中有来自localhost的匿名用户行,''@'localhost'则该行将被视为比具有通配符主机的用户更具体'user'@'%'。这就是为什么必须同时提供的原因'user'@'localhost'

您可以在本页底部看到更详细的说明。


5

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

本地主机仅允许本地连接。

(因此,开始时,如果不需要到数据库的远程连接,则可以立即删除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从本地主机连接,将使用该用户)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.