[英]User can't access a database
在我的PHP脚本中,我正在访问两个数据库db1
和db2
。 我有一个用户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,我看到了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
?
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在具有通配符主机名(%)的用户中优先,如下所示:
根据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.