ข้อผิดพลาดของ MySQL: การเข้าถึงถูกปฏิเสธสำหรับผู้ใช้ 'a' @ 'localhost' (ใช้รหัสผ่าน: ใช่)


22

'a'@'%'ผมใช้บัญชีรากสร้างบัญชี แต่ฉันไม่สามารถใช้บัญชีเพื่อเชื่อมต่อกับเซิร์ฟเวอร์ 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 'a'@'%'แต่ผมเห็นปัญหานี้ไม่กี่ครั้งผมไม่ทราบว่าสิ่งที่เป็นเหตุผลที่แก้ปัญหาได้อย่างชัดเจนความหมายของการเป็นเจ้าภาพที่นอกเหนือไปจาก เพื่อบันทึกเป็นครั้งแรกและครั้งที่สองคือ'a'@'%' 'a'@'localhost'
com

คุณช่วยทดสอบกับ mysql เวอร์ชั่นที่ต่ำกว่าได้ไหม ..
อับดุลมานาฟ

ใช้รายละเอียดการเข้าสู่ระบบ Cpanel เพื่อเชื่อมต่อ
Abu Fahim

ในกรณีของฉันฉันมีบัญชีที่ไม่ระบุชื่อสามบัญชีที่สร้างขึ้นโดยค่าเริ่มต้นการลบบัญชีจะช่วยแก้ปัญหานี้ได้
Joaquín L. Robles

คำตอบ:


26

นี่เป็นวิธีที่รวดเร็วและสกปรกสำหรับการตรวจสอบว่า MySQL ทำการพิสูจน์ตัวตนสำเร็จหรือไม่

กรุณาเรียกใช้แบบสอบถามนี้:

SELECT USER(),CURRENT_USER();

USER ()รายงานว่าคุณพยายามตรวจสอบสิทธิ์ใน mysqld อย่างไร

CURRENT_USER ()รายงานว่าคุณได้รับอนุญาตให้ตรวจสอบสิทธิ์โดย mysqld ได้อย่างไร

บางครั้งUSER()และCURRENT_USER()แตกต่างกัน นั่นเป็นเพราะการตรวจสอบ mysql เป็นไปตามโปรโตคอล specfic

ตามคู่มือการศึกษาการรับรอง MySQL 5.0

ป้อนคำอธิบายรูปภาพที่นี่

หน้า 486,487 ระบุขั้นตอนวิธีการพิสูจน์ตัวตนของ mysql ต่อไปนี้:

การควบคุมการเข้าถึงไคลเอ็นต์มีสองขั้นตอน:

ในระยะแรกไคลเอนต์พยายามเชื่อมต่อและเซิร์ฟเวอร์ยอมรับหรือปฏิเสธการเชื่อมต่อ สำหรับความพยายามที่จะประสบความสำเร็จบางรายการในตารางผู้ใช้จะต้องตรงกับโฮสต์ที่ลูกค้าเชื่อมต่อชื่อผู้ใช้และรหัสผ่าน

ในขั้นตอนที่สอง (ซึ่งเกิดขึ้นเฉพาะเมื่อไคลเอนต์เชื่อมต่อเรียบร้อยแล้ว) เซิร์ฟเวอร์จะตรวจสอบทุกแบบสอบถามที่ได้รับจากลูกค้าเพื่อดูว่าลูกค้ามีสิทธิ์เพียงพอที่จะดำเนินการหรือไม่

เซิร์ฟเวอร์จับคู่ไคลเอ็นต์กับรายการในตารางการให้สิทธิ์ตามโฮสต์ที่ไคลเอ็นต์เชื่อมต่อและผู้ใช้ที่ลูกค้าให้ อย่างไรก็ตามมีความเป็นไปได้ที่จะมีมากกว่าหนึ่งระเบียนที่ตรงกับ:

อาจระบุค่าโฮสต์ในตารางการให้สิทธิ์เนื่องจากรูปแบบมีค่าสัญลักษณ์แทน ถ้าตารางทุนมีรายการจาก myhost.example.com, %.example.com, %.comและทั้งหมดของพวกเขาให้ตรงกับลูกค้าที่เชื่อมต่อจาก%myhost.example.com

รูปแบบไม่ได้รับอนุญาตสำหรับค่าผู้ใช้ในรายการตารางให้ แต่ชื่อผู้ใช้อาจได้รับเป็นสตริงว่างเพื่อระบุผู้ใช้ที่ไม่ระบุชื่อ สตริงว่างตรงกับชื่อผู้ใช้และทำหน้าที่เป็นตัวแทน

เมื่อโฮสต์และค่าผู้ใช้ในระเบียนผู้ใช้มากกว่าหนึ่งระเบียนตรงกับไคลเอ็นต์เซิร์ฟเวอร์จะต้องตัดสินใจว่าจะใช้รายการใด ทำได้โดยการเรียงลำดับระเบียนที่มีค่าคอลัมน์โฮสต์และผู้ใช้เฉพาะที่สุดก่อนและเลือกระเบียนที่ตรงกันที่เกิดขึ้นเป็นอันดับแรกในรายการที่เรียงลำดับการเรียงลำดับจะเกิดขึ้นดังนี้:

ในคอลัมน์โฮสต์ค่าที่แท้จริงเช่นlocalhost, 127.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 เป็นโฮสต์ผู้ใช้ ไม่มีดัชนีอื่น ๆ สิ่งนี้อนุญาตให้มีชื่อผู้ใช้หลายครั้ง แต่ละเหตุการณ์สามารถมีรหัสผ่านที่แตกต่างกันหรือไม่มีรหัสผ่าน สิ่งนี้อนุญาตให้ผู้ใช้ 'dbuser' ล็อกอินแบบโลคัล (dbuser @ localhost) โดยไม่ใช้รหัสผ่านและล็อกอินผู้ใช้เดียวกันจากเซิร์ฟเวอร์อื่นภายใน netblock ที่กำหนด (dbuser@'10.1.2.20 ') ด้วยรหัสผ่านเช่น' pass1 'และผู้ใช้นั้นเพื่อเข้าสู่ระบบ จากระยะไกลจากที่ใดก็ได้ (dbuser @ '%') ด้วยรหัสผ่านระยะไกลเช่น 'pass2'

เมื่อพิจารณาจากอัลกอริทึมการพิสูจน์ตัวตนที่ MySQL ใช้นั้นไม่มีข้อ จำกัด สำหรับผู้ใช้ที่มีหรือไม่มีรหัสผ่าน

นี่คือเหตุผลที่คู่มือการศึกษาเพื่อรับรอง MySQL 5.0 กล่าวไว้ในหน้า 498 ย่อหน้าที่ 6ในหัวข้อย่อยของวิธีการล้างกระบวนการตรวจสอบ:

ใน Unix, MySQL มาพร้อมกับสคริปต์ mysql_secure_installation ที่สามารถทำการดำเนินการที่เกี่ยวข้องกับความปลอดภัยที่เป็นประโยชน์มากมายในการติดตั้งของคุณ สคริปต์มีความสามารถดังต่อไปนี้:

  • ตั้งรหัสผ่านสำหรับบัญชีรูท
  • ลบบัญชี root ที่สามารถเข้าถึงได้จากระยะไกล
  • ลบบัญชีผู้ใช้ที่ไม่ระบุชื่อ สิ่งนี้จะช่วยเพิ่มความปลอดภัยเนื่องจากป้องกันไม่ให้ใครก็ตามที่เชื่อมต่อกับเซิร์ฟเวอร์ MySQL เป็นรูทจากโฮสต์ระยะไกล ผลลัพธ์คือทุกคนที่ต้องการเชื่อมต่อในฐานะรูทจะต้องสามารถเข้าสู่ระบบบนโฮสต์เซิร์ฟเวอร์ได้ซึ่งจะช่วยป้องกันการโจมตีเพิ่มเติม
  • ลบฐานข้อมูลทดสอบ (หากคุณลบบัญชีที่ไม่ระบุชื่อคุณอาจต้องการลบฐานข้อมูลทดสอบที่พวกเขาสามารถเข้าถึงได้)

ใช่ฉันพยายามมันจะส่งคืนแถวที่ไม่มีรหัสผ่าน ขอบคุณสำหรับคำอธิบายที่ยอดเยี่ยมของคุณและแนะนำหนังสือรับรอง MySQL
เพียงผู้เรียน

2
Rolando หากมีชื่อผู้ใช้สองชื่อเหมือนกันอยู่ในตาราง mysql.user ชื่อหนึ่งที่มีรหัสผ่านและไม่มีชื่อนั่นหมายความว่า MySQL ปฏิเสธการรับรองความถูกต้องเมื่อไม่ได้ใช้รหัสผ่านใช่หรือไม่
Craig Efrein

@ Craig - คำถามของคุณสำคัญมาก ฉันจะถ่ายโอนไปยังคำตอบของฉันและตอบมันที่นั่น
RolandoMySQLDBA

ขอบคุณสำหรับคำตอบโดยละเอียดในกรณีของฉันฉันมีผู้ใช้ที่ไม่ระบุชื่อกำหนดค่าอย่างใด
SoWeLie

@RolandoMySQLDBA สามารถพบข้อมูลทั้งหมดในคู่มือการศึกษาใบรับรองได้แล้วในคู่มือออนไลน์ MySQL?
Pacerier

5

wildcard ของโฮสต์ '%' ไม่ตรงกับ 'localhost' โดยค่าเริ่มต้นไคลเอนต์ mysql จะพยายามเชื่อมต่อผ่านซ็อกเก็ตแทน tcp (มักจะเป็นสถานที่เช่น /var/lib/mysql/mysql.sock)

คุณสามารถเปลี่ยนการอนุญาตเป็น 'a' @ 'localhost' หรือบังคับให้ไคลเอ็นต์ทำงานผ่านสแต็ก TCP เช่น:

mysql -u a -p --protocol=TCP

ฉันพยายาม แต่ก็ยังไม่มีโชค
เพียงแค่ผู้เรียน

จะกำหนดค่าตัวเลือกนี้my.cnfได้อย่างไรโดยไม่ต้องการพารามิเตอร์นี้อีกต่อไป?
shgnInc

1
คุณทำไม่ได้ หากคุณไม่ระบุชื่อโฮสต์ -h จะถือว่า "localhost" หมายความว่ากำลังมองหาซ็อกเก็ตไม่ใช่พอร์ต TCP ที่ไม่มีแฟล็กโปรโตคอล คุณสามารถตั้งค่า shell aliase ได้หากคุณเบื่อที่จะพิมพ์อาร์กิวเมนต์ทั้งหมด
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

ฉันก็ทำเช่นเดียวกันกับที่ถามในคำถาม และทำสิ่งที่คุณพูดในคำตอบของคุณ แต่ก็ยังมีปัญหาเดียวกัน
อับดุลมานาฟ

คุณสามารถให้ผลลัพธ์จากแบบสอบถามต่อไปนี้: เลือกผู้ใช้โฮสต์จาก mysql.user;
Craig Efrein

ใช่ MySQL กำลังฟังพอร์ต 3306 ดูการแก้ไขของฉัน
เพียงแค่เป็นผู้เรียนที่

คุณอาจต้องการลอง mysql -u user -p -h 127.0.0.1 หากใช้งานได้ฉันเชื่อว่าเป็น mysql ที่ไม่รู้วิธีแก้ปัญหา localhost รายการสำหรับ localhost ที่ชี้ไปที่ 127.0.0.1 ในไฟล์ / etc / hosts ของคุณจะแก้ไขได้
Craig Efrein

คุณใช้สิทธิ์ล้างข้อมูลหรือไม่?
Craig Efrein

1

ตามที่ @atxdba อธิบายไว้ในการเชื่อมต่อ mysql daemon จากระยะไกลที่ไม่ได้เชื่อมต่อผ่านซ็อกเก็ตดังนั้นคุณต้องเชื่อมต่อจากระยะไกลผ่าน TCP

สำหรับสิ่งนี้คุณควรระบุการ--protocol=TCPเชื่อมต่อแต่ละรายการ แม้ว่าคุณสามารถตั้งค่าในmy.cnfเซิร์ฟเวอร์:

[client]
protocol=tcp
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.