用户无法访问数据库

时间:2012-12-23 15:02:04

标签: mysql

在我的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,我发现db1db2相同的权限

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

7 个答案:

答案 0 :(得分:23)

localhost与MySQL中的%不匹配。它似乎应该,但事实上它不应该。您必须为user@localhost权限和每个数据库的权限分别授予USAGE权限。

或者您可以{em> 匹配user@127.0.0.1 %进行连接。使用localhost的IP地址似乎应该与localhost完全相同,但事实并非如此。您需要在mysql.user表中(以及在您的案例中的mysql.db表中)有两行才能启用这两行。

演示localhost和127.0.0.1之间的区别:

mysql -h localhost身份连接使用UNIX套接字接口,并绕过TCP / IP。这可能会稍微好一点,但它会对上面描述的授权匹配产生影响。

您可以通过mysql -h 127.0.0.1连接来强制本地TCP / IP连接。然后它将获得您对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'

答案 1 :(得分:6)

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

FLUSH PRIVILEGES;

答案 2 :(得分:2)

这很可能与GRANTs无关。

由于MySQL中存在默认用户,因此具有不正确访问权限的一个常见原因是。特别是在''表中User(匿名用户)和/或Host mysql.user的{​​{1}}。由于MySQL处理authentication and proxy users的方式以及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地址,主机名,用户名等)> '%'> ''

大多数情况下,应用程序服务器/客户端与数据库在同一主机上运行,​​导致主机名在身份验证期间被选为localhostmysql -u jeffrey使用与jeffrey@localhost而不是''@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

答案 3 :(得分:2)

我想我会添加一个答案。我在ubuntu上尝试这个。尝试了补助金,冲洗,没有任何工作(这是由apt-get install mysql-server之后立即执行)。只是为了笑容,我反弹了服务器,这是有效的,我的新用户现在可以登录。我做了:

sudo service mysql restart

我不知道那有什么用,但确实如此。

答案 4 :(得分:1)

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

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

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

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

答案 5 :(得分:0)

根据mysql手册here

  

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

     

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

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

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

答案 6 :(得分:-1)

我过去遇到过同样的问题。你试过以下这个吗?

GRANT ALL ON `db1`.* TO 'myuser'@'%' IDENTIFIED BY PASSWORD '*7733323232...';
GRANT ALL ON `db2`.* TO 'myuser'@'%' IDENTIFIED BY PASSWORD '*7733323232...';
FLUSH PRIVILEGES;