繁体   English   中英

用户无法访问数据库

[英]User can't access a database

在我的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

localhost与MySQL中的%不匹配。 似乎应该,但实际上并非如此。 您必须分别为user@localhost授予特权,以分别具有USAGE特权和每个数据库的特权。

或者,你可以连接为user@127.0.0.1 已经匹配% 为本地主机使用IP地址似乎应该与本地主机相同,但事实并非如此。 您需要在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'

如果尚未执行此操作,则需要运行flush privileges以便mysql知道有更改并为用户重新加载特权表:

FLUSH PRIVILEGES;

这很可能与GRANT无关。

拥有错误访问权限的一个很常见的原因是由于 MySQL中存在默认用户 特别是在mysql.user表中, User (匿名用户)和/或Host带有'' 由于MySQL处理身份验证和代理用户的方式以及 mysql.user表条目上使用的排序规则,因此最终可能会使用一个意外用户而不是用于身份验证的用户。

使用SELECT USER(); 找出在身份验证和SELECT CURRENT_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@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

只是以为我会添加一个答案。 我在ubuntu上尝试过这个。 尝试了授予,刷新,没有任何效果(通过apt-get install mysql-server立即执行)。 我只是因为咧嘴笑而跳开服务器,它正常工作了,新用户现在可以登录了。 我做了:

sudo service mysql restart

我不知道这有什么用,但是确实有用。

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

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

否则,在数据库安装期间创建的匿名用户@localhost在具有通配符主机名(%)的用户中优先,如下所示:

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

根据mysql手册在这里

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM