MySQL错误:用户'a'@'localhost'的访问被拒绝(使用密码:是)


22

我使用root帐户创建了该帐户'a'@'%'。但是,当指定host参数时,无法使用该帐户连接到MySQL服务器。没有-h参数,我可以成功连接。请参阅下面的成绩单。我希望有人能帮助我解释一下。谢谢。

mysql> grant all on *.* to 'a'@'%' identified by a;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a' at line 1
mysql> grant all on *.* to 'a'@'%' identified by 'a';
Query OK, 0 rows affected (0.00 sec)

mysql> show grants for 'a'@'%';
+-----------------------------------------------------------------------------------------------------------+
| Grants for a@%                                                                                            |
+-----------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'a'@'%' IDENTIFIED BY PASSWORD '*667F407DE7C6AD07358FA38DAED7828A72014B4E' |
+-----------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> exit
Bye

[root@localhost ~]# mysql -h localhost -u a -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'a'@'localhost' (using password: YES)
[root@localhost ~]# mysql -h 127.0.0.1 -u a -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'a'@'localhost' (using password: YES)
[root@localhost ~]# mysql -u a -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'a'@'localhost' (using password: YES)
[root@localhost ~]# mysql -u a
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 5.5.17 MySQL Community Server (GPL)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
mysql> status
--------------
mysql  Ver 14.14 Distrib 5.5.17, for Linux (x86_64) using readline 5.1

Connection id:      20
Current database:   
Current user:       a@localhost
SSL:            Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server version:     5.5.17 MySQL Community Server (GPL)
Protocol version:   10
Connection:     Localhost via UNIX socket
Server characterset:    utf8
Db     characterset:    utf8
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:        /var/lib/mysql/mysql.sock
Uptime:         15 days 15 hours 20 min 18 sec

Threads: 1  Questions: 40  Slow queries: 0  Opens: 41  Flush tables: 1  Open tables: 4  Queries per second avg: 0.000
--------------

mysql> 

编辑:

是的,MySQL正在监听端口3306。

[root@localhost ~]# nmap localhost

Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2012-01-18 07:35 CST
Interesting ports on localhost.localdomain (127.0.0.1):
Not shown: 1674 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
25/tcp   open  smtp
111/tcp  open  rpcbind
631/tcp  open  ipp
840/tcp  open  unknown
3306/tcp open  mysql

Nmap finished: 1 IP address (1 host up) scanned in 0.064 seconds
[root@localhost ~]# 

1
我不是MySql的专家,但我几次看到此问题,不知道是什么原因,解决方案除了之外还明确定义了host 'a'@'%'。因此,第一条记录为'a'@'%',第二条记录为'a'@'localhost'
com 2012年

您可以用较低的mysql版本测试同一件事吗?
Abdul Manaf 2012年

使用Cpanel登录详细信息进行连接。
阿布·法欣

在我来说,我不得不默认情况下创建了三个annonymous帐户,删除它们会解决这个问题
华金属罗伯斯

Answers:


26

这是检查MySQL如何执行成功身份验证的快速方法。

请运行以下查询:

SELECT USER(),CURRENT_USER();

USER()报告您如何尝试在mysqld中进行身份验证

CURRENT_USER()报告mysqld如何允许您进行身份验证

有时候,USER()CURRENT_USER()是不同的。这是因为mysql身份验证遵循特定协议。

根据MySQL 5.0认证学习指南

在此处输入图片说明

第486,487页陈述了有关mysql的身份验证算法的以下内容:

客户端访问控制分为两个阶段:

在第一阶段,客户端尝试连接,而服务器接受或拒绝连接。为了成功尝试,用户表中的某些条目必须与客户端连接的主机,用户名和密码匹配。

在第二阶段(仅当客户端已经成功连接时才发生),服务器检查它从客户端收到的每个查询,以查看客户端是否具有执行该客户端的足够特权。

服务器根据客户端连接到的主机和客户端提供的用户,将客户端与授权表中的条目进行匹配。但是,可能有多个记录匹配:

可以将授权表中的主机值指定为包含通配符值的模式。如果授权表包含的条目 myhost.example.com%.example.com%.com,和%,他们都匹配一个客户,谁从连接myhost.example.com

授予表条目中的“用户”值不允许使用模式,但是可以将用户名指定为空字符串以指定匿名用户。空字符串匹配任何用户名,因此有效地充当通配符。

当多个用户表记录中的主机和用户值与客户端匹配时,服务器必须决定使用哪个客户端。为此,它首先对具有最特定的“主机”和“用户”列值的记录进行排序,然后选择在排序列表中最先出现的匹配记录,排序如下:

在“主机列”中,文字值(例如localhost127.0.0.1)和myhost.example.com排序在诸如%.example.com 其中具有模式字符的值之前。模式值根据其具体程度进行排序。例如,%.example.com比更加具体%.com,而比更加具体%

在“用户”列中,非空白用户名在空白用户名之前排序。也就是说,非匿名用户排在匿名用户之前。

服务器在启动时执行此排序。它将授权表读入内存,对其进行排序,然后使用内存中的副本进行访问控制。

从此描述中,您不必担心mysql.user表的顺序,因为有一个如前所述排序的授予表的内存副本。

关于您的登录方式,仅mysql -u a有效。返回并再次登录并运行这些命令

SELECT USER(),CURRENT_USER();
SELECT user,host,password FROM mysql.user;

确保

  • 每个用户都有一个密码。
  • 没有匿名用户(当用户为空时)

这只是一个猜测,但我怀疑mysql -u a是通过localhost连接的,因为未指定连接协议时,默认设置是通过套接字文件进行连接。可能存在mysql.user允许匿名localhost连接的条目。

运行此查询:

SELECT user,host,password FROM mysql.user WHERE user='' AND host='localhost';

如果您返回没有密码的行,那就充分说明了为什么会mysq -u a起作用。

更新2012-01-19 11:12 EDT

Craig Efrein提出了一个有趣的问题:如果mysql.user表中存在两个相同的用户名,一个用户名带有密码,一个用户名没有密码,这是否意味着MySQL在不使用密码时拒绝身份验证?

这个问题是关于MySQL用户身份验证的一个很好的提示。

请注意,mysql.user的主键是host,user。没有其他索引。这允许多次出现用户名。每个事件可以具有不同的密码,也可以没有密码。这允许用户'dbuser'使用不使用密码的本地登录(dbuser @ localhost),并且使用给定Netblock(dbuser@'10.1.2.20')中的另一台服务器使用相同的用户登录名,密码为'pass1',并且该用户可以登录使用“ pass2”之类的远程密码从任何地方(dbuser @'%')远程进行。

给定MySQL使用的身份验证算法,无论是否存在密码,对用户都没有限制。

这就是为什么《MySQL 5.0认证研究指南》在第498页第6段的要点中指出了如何清理身份验证过程的原因:

在Unix上,MySQL附带了一个mysql_secure_installation脚本,该脚本可以对您的安装执行一些与安全性有关的有用操作。该脚本具有以下功能:

  • 为root帐户设置密码
  • 删除所有可远程访问的根帐户。
  • 删除匿名用户帐户。这样可以提高安全性,因为它可以防止任何人以root用户身份从远程主机连接到MySQL服务器。结果是任何想以root用户身份连接的人都必须首先能够登录服务器主机,这为攻击提供了额外的障碍。
  • 删除测试数据库(如果删除匿名帐户,您可能还希望删除其有权访问的测试数据库)。

是的,我尝试过,它确实返回没有密码的行。感谢您的出色解释,并推荐了MySQL认证书。
只是一个学习者

2
Rolando,如果mysql.user表中存在两个相同的用户名,一个用户名带有密码,一个用户名没有密码,这是否意味着MySQL在不使用密码时拒绝身份验证?
Craig Efrein 2012年

@Craig-您的问题非常值得注意。我将其转换成我的答案并在那里解决。
RolandoMySQLDBA 2012年

感谢您提供详细的答案,就我而言,我以某种方式配置了匿名用户。
SoWeLie 2013年

@RolandoMySQLDBA,可认证学习指南中的所有信息已经被在MySQL在网上找到手册?
和平者

5

'%'主机通配符与'localhost'不匹配。默认情况下,mysql客户端将尝试通过套接字而不是tcp进行连接(通常是/var/lib/mysql/mysql.sock之类的地方)。

您可以将授予更改为'a'@'localhost',也可以强制客户端通过TCP堆栈进行操作,例如:

mysql -u a -p --protocol=TCP

我试过了,但还是没有运气。
只是一个学习者

如何在my.cnf不再需要该参数的情况下配置该选项?
shgnInc

1
你不知道 如果未指定-h主机名,则假定它为“ localhost”,这表示它正在查找套接字,而不是没有协议标志的TCP端口。如果您厌倦了键入所有参数,则可以设置外壳别名。
atxdba

2

您是否检查以确保MySQL确实在监听3306?运行netstat -tlpn并提供结果。如果您没有看到3306,则可能没有。

my.cnf中,您应验证--skip-networking已被注释掉

[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
language        = /usr/share/mysql/English
bind-address    = 65.55.55.2
# skip-networking

我也做了同样的问题。并且回答了您说的内容,但仍然存在相同的问题。
Abdul Manaf 2012年

您能否提供以下查询的结果:选择用户,从mysql.user主机;
Craig Efrein 2012年

是的,MySQL正在监听端口3306。请参见我的编辑。
只是一个学习者

您可能还想尝试mysql -u user -p -h 127.0.0.1。如果可行,那么我相信它的mysql不知道如何解析本地主机。localhost指向/ etc / hosts文件中的127.0.0.1的条目将解决该问题。
Craig Efrein 2012年

您是否运行了“冲洗特权”?
Craig Efrein 2012年

1

如@atxdba所述,要从远程连接而不是通过套接字连接的mysql守护进程,因此您需要通过TCP从远程连接。

为此,您应指定--protocol=TCP每个连接数。虽然,您可以my.cnf在服务器上设置它:

[client]
protocol=tcp
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.