用户无法访问数据库
在我的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中存在默认用户 。 与那些特别''
的User
(匿名用户)和/或Host
在mysql.user
表。 由于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@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