14

在我的 PHP 脚本中,我正在访问两个数据库db1db2. 我有一个myuser@localhost可以访问db1但无法访问的用户db2

mysql.user表中选择时,有一条记录,该用户的主机是通配符%,没有localhost主机。

SELECT user, host FROM mysql.user WHERE user = 'myuser'; 给我吗:

+------------+------+
| user       | host |
+------------+------+
| myuser     | %    |
+------------+------+
1 row in set (0.00 sec)

查看该用户的 GRANTS ,我看到与 for 相同的db1权限db2

SHOW GRANTS FOR 'myuser'@'%';

+-----------------------------------------------------------------------------------------------------------+
| Grants for myuser@%                                                                                   |
+-----------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'myuser'@'%' IDENTIFIED BY PASSWORD '*7733323232...' |
| GRANT ALL PRIVILEGES ON `db1`.* TO 'myuser'@'%'                                                |
| GRANT ALL PRIVILEGES ON `db2`.* TO 'myuser'@'%'                                              |
+-----------------------------------------------------------------------------------------------------------+

在我的 PHP 脚本中,我可以访问db1,但是出现错误:INSERT command denied to user 'myuser'@'localhost' for table 'HISTORY'.

它说用户是myuser@localhost并且人们建议添加权限myuser@localhost但是,为什么这个用户有权访问db1而不是db2

4

7 回答 7

26

localhost%在 MySQL中不匹配。看起来应该,但实际上并没有。您必须分别授予 权限user@localhostUSAGE每个数据库的权限。

或者你可以连接为user@127.0.0.1which does match %。使用 localhost 的 IP 地址似乎应该与 localhost 相同,但事实并非如此。您需要在mysql.user表格中有两行(在您的情况下也在mysql.db表格中)以启用两者。

为了演示 localhost 和 127.0.0.1 之间的区别:

连接 asmysql -h localhost使用 UNIX 套接字接口,并绕过 TCP/IP。这对于性能可能会稍好一些,但它对上述授权匹配有影响。

您可以通过连接为 来强制本地 TCP/IP 连接mysql -h 127.0.0.1。然后它将获取您对 的赠款myuser@%

因此,要为套接字接口和 TCP/IP 接口获取相同的用户、密码和权限,您需要运行以下所有语句:

GRANT USAGE ON *.* TO 'myuser'@'%' IDENTIFIED BY PASSWORD '*7733323232...'
GRANT USAGE ON *.* TO 'myuser'@'localhost' IDENTIFIED BY PASSWORD '*7733323232...'
GRANT ALL PRIVILEGES ON `db1`.* TO 'myuser'@'%'
GRANT ALL PRIVILEGES ON `db1`.* TO 'myuser'@'localhost'
GRANT ALL PRIVILEGES ON `db2`.* TO 'myuser'@'%'
GRANT ALL PRIVILEGES ON `db2`.* TO 'myuser'@'localhost'
于 2012-12-28T17:59:09.770 回答
6

如果您还没有这样做,您需要运行flush privileges以便mysql知道发生了更改并为用户重新加载权限表:

FLUSH PRIVILEGES;
于 2012-12-23T15:16:06.793 回答
2

这很可能与 GRANT 无关。

访问权限不正确的一个非常常见的原因是MySQL 中存在默认用户。特别是''对于User(匿名用户)和/或Hostmysql.user表格中的那些。由于 MySQL 处理身份验证和代理用户的方式,以及用于mysql.user表条目的排序规则,最终可能会使用一个意想不到的用户,而不是他们用于身份验证的用户。

用于SELECT USER();找出在身份验证期间使用的连接用户,并SELECT CURRENT_USER();找出在当前会话期间其权限适用的有效用户

并来自http://dev.mysql.com/doc/refman/5.6/en/connection-access.html

一种常见的误解是,对于给定的用户名,当服务器尝试查找连接的匹配项时,首先使用明确命名该用户的所有行。这不是真的。如果您能够连接到服务器,但您的权限不是您所期望的,您可能正在被验证为其他帐户。

mysql.user类似于以下的表格

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| %         | root     | ... (root from any host)
| %         | jeffrey  | ... (jeffrey from any host)
| localhost | root     | ... (root from localhost)
| localhost |          | ... (any user from localhost)
+-----------+----------+-

变成,

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| localhost | root     | ...
| localhost |          | ...
| %         | jeffrey  | ...
| %         | root     | ...
+-----------+----------+-

每当服务器将用户表读入内存时,以处理多个匹配项。
当客户端尝试连接时,服务器会按排序顺序查看行并使用与客户端主机名和用户名匹配的第一行。
优先级为:值(IP 地址、主机名、用户名等)'%'>>''

大多数情况下,应用程序服务器/客户端与数据库在同一主机上运行,​​导致localhost在身份验证期间获取主机名。
mysql -u jeffrey使用jeffrey@localhostwhich 匹配''@localhost而不是jeffrey@%.

执行$MYSQL_HOME/bin/mysql_secure_installation将删除匿名用户,同时保护安装,减轻这种意外行为。

还要检查:
[1] http://bugs.mysql.com/bug.php?id=36576(最后检查评论)
[2] http://bugs.mysql.com/bug.php?id=69570

于 2014-07-19T12:21:41.873 回答
2

只是想我会添加一个答案。我在ubuntu上试过这个。尝试了授权,刷新,没有任何效果(这是在 apt-get install mysql-server 之后立即执行的)。只是为了笑,我退回了服务器,这很有效,我的新用户现在可以登录了。我做了:

sudo service mysql restart

我不知道那有效,但确实有效。

于 2014-09-15T15:26:59.670 回答
1

您还必须授予 'myuser'@'localhost' 权限:

GRANT ALL PRIVILEGES ON `db1`.* TO 'myuser'@'localhost';
GRANT ALL PRIVILEGES ON `db2_beta`.* TO 'myuser'@'localhost';

否则,在 db install 期间创建的匿名用户 @localhost 优先于具有通配符主机名 (%) 的用户,如下所述:

http://dev.mysql.com/doc/refman/5.5/en/adding-users.html

于 2012-12-23T15:32:29.767 回答
0

根据这里的mysql手册:

如果您使用 GRANT、REVOKE 或 SET PASSWORD 等帐户管理语句间接修改授权表,服务器会注意到这些更改并立即将授权表再次加载到内存中。

如果您直接使用 INSERT、UPDATE 或 DELETE 等语句修改授权表,则您的更改不会影响权限检查,直到您重新启动服务器或告诉它重新加载表。如果您直接更改授权表但忘记重新加载它们,则您的更改在重新启动服务器之前无效。这可能会让您想知道为什么您的更改似乎没有任何区别!

在大多数情况下,这似乎是正确的。但是,在我的情况下,我使用的是 Amazon Web Services (AWS) RDS mysql 实例。在多次尝试授予用户权限失败后,我尝试了 aFLUSH PRIVILEGES并且数据库立即对用户可见。如果您在 Amazon Web Services RDS 平台上寻找解决方案时遇到此问题,您可能想尝试一下,看看它是否有帮助。

此 SO 问题包含此问题的最完整解决方案,并且是大多数搜索结果中的第一个,因此我想为使用 RDS 的任何人添加此响应。希望它可以为 RDS 管理员节省一些时间。

于 2014-05-14T09:47:22.840 回答
-1

我过去也遇到过同样的问题。您是否尝试过以下操作?

GRANT ALL ON `db1`.* TO 'myuser'@'%' IDENTIFIED BY PASSWORD '*7733323232...';
GRANT ALL ON `db2`.* TO 'myuser'@'%' IDENTIFIED BY PASSWORD '*7733323232...';
FLUSH PRIVILEGES;
于 2013-01-04T16:03:55.307 回答