Kesalahan MySQL: Akses ditolak untuk pengguna 'a' @ 'localhost' (menggunakan kata sandi: YES)

22

Saya menggunakan akun root membuat akun 'a'@'%'. Tapi saya tidak bisa menggunakan akun untuk terhubung ke server MySQL ketika saya menentukan parameter host. Saya dapat berhasil terhubung tanpa -hparameter. Silakan lihat transkrip di bawah ini. Saya harap seseorang dapat membantu saya menjelaskannya. Terima kasih.

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> 

Edit:

Ya, MySQL mendengarkan pada port 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 ~]# 
Hanya seorang pembelajar
sumber
1
Saya bukan spesialis di MySql, tapi saya melihat masalah ini beberapa kali, saya tidak tahu apa alasannya, solusinya adalah definisi host secara eksplisit 'a'@'%'. jadi, catatan pertama adalah 'a'@'%', dan yang kedua adalah 'a'@'localhost'.
com
dapatkah Anda menguji hal yang sama dengan versi mysql yang lebih rendah ..?
Abdul Manaf
gunakan Cpanel Login Details Untuk menghubungkan.
Abu Fahim
Dalam kasus saya, saya memiliki tiga akun anonim yang dibuat secara default, menghapusnya akan menyelesaikan masalah ini
Joaquín L. Robles

Jawaban:

26

Berikut adalah metode cepat dan kotor untuk memeriksa bagaimana MySQL melakukan otentikasi yang berhasil.

Silakan jalankan kueri ini:

SELECT USER(),CURRENT_USER();

USER () melaporkan bagaimana Anda mencoba mengotentikasi di mysqld

CURRENT_USER () melaporkan bagaimana Anda diizinkan untuk mengautentikasi oleh mysqld

Terkadang, USER()dan CURRENT_USER()berbeda. Itu karena otentikasi mysql mengikuti protokol tertentu.

Menurut Panduan Studi Sertifikasi MySQL 5.0

masukkan deskripsi gambar di sini

halaman 486.487 menyatakan berikut ini pada algoritma otentikasi mysql:

Ada dua tahap kontrol akses klien:

Pada tahap pertama, klien mencoba untuk terhubung dan server menerima atau menolak koneksi. Agar upaya berhasil, beberapa entri dalam tabel pengguna harus cocok dengan host tempat klien terhubung, nama pengguna, dan kata sandi.

Pada tahap kedua (yang terjadi hanya jika klien telah terhubung dengan sukses), server memeriksa setiap permintaan yang diterima dari klien untuk melihat apakah klien memiliki hak yang cukup untuk menjalankannya.

Server mencocokkan klien dengan entri dalam tabel hibah berdasarkan tuan rumah dari mana klien terhubung dan pengguna yang disediakan klien. Namun, ada kemungkinan lebih dari satu catatan yang cocok:

Nilai host di tabel hibah dapat ditentukan karena pola berisi nilai wildcard. Jika tabel hibah berisi entri dari myhost.example.com, %.example.com, %.com, dan %, semua dari mereka cocok dengan klien yang menghubungkan dari myhost.example.com.

Pola tidak diizinkan untuk nilai-nilai Pengguna dalam entri tabel hibah, tetapi nama pengguna dapat diberikan sebagai string kosong untuk menentukan pengguna anonim. String kosong cocok dengan nama pengguna apa pun dan karenanya secara efektif bertindak sebagai wildcard.

Ketika Host dan nilai-nilai Pengguna dalam lebih dari satu catatan tabel pengguna cocok dengan klien, server harus memutuskan mana yang akan digunakan. Itu melakukan ini dengan menyortir catatan dengan nilai kolom Host dan Pengguna yang paling spesifik terlebih dahulu, dan memilih catatan yang cocok yang muncul pertama kali dalam daftar yang diurutkan, Penyortiran terjadi sebagai berikut:

Dalam Host Kolom, nilai-nilai literal seperti localhost, 127.0.0.1, dan myhost.example.comsemacam depan nilai-nilai seperti %.example.com yang memiliki karakter pola di dalamnya. Nilai pola diurutkan berdasarkan seberapa spesifik mereka. Misalnya, %.example.comlebih spesifik daripada %.com, yang lebih spesifik daripada %.

Di kolom Pengguna, nama pengguna yang tidak kosong mengurutkan di depan nama pengguna yang kosong. Artinya, pengguna non-anonim mengurutkan dari pengguna anonim.

Server melakukan penyortiran ini ketika dimulai. Itu membaca tabel hibah ke dalam memori, mengurutkannya, dan menggunakan salinan dalam memori untuk kontrol akses.

Dari uraian ini, Anda tidak perlu khawatir tentang urutan tabel mysql.user karena ada salinan dalam memori dari tabel hibah yang diurutkan seperti yang disebutkan sebelumnya.

Berkenaan dengan bagaimana Anda masuk, hanya mysql -u aberfungsi. Kembali dan masuk lagi dan jalankan perintah ini

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

Pastikan bahwa

  • setiap pengguna memiliki kata sandi.
  • tidak ada pengguna anonim (saat pengguna kosong)

Ini hanya dugaan, tetapi saya curiga mysql -u amenghubungkan melalui localhost karena ketika protokol koneksi tidak ditentukan, defaultnya adalah untuk terhubung melalui file socket. Mungkin ada entri di mysql.useryang memungkinkan koneksi host lokal anonim.

Jalankan kueri ini:

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

Jika Anda mendapatkan kembali baris tanpa kata sandi, itu sepenuhnya menjelaskan alasannya mysq -u a berfungsi.

UPDATE 2012-01-19 11:12 EDT

Craig Efrein memunculkan pertanyaan yang menarik: jika dua nama pengguna yang identik ada di tabel mysql.user, satu dengan kata sandi dan satu tanpa, apakah itu berarti bahwa MySQL menolak otentikasi ketika tidak menggunakan kata sandi?

Pertanyaan ini adalah pertanyaan bagus tentang otentikasi pengguna MySQL.

Harap dicatat bahwa kunci utama mysql.user adalah host, pengguna. Tidak ada indeks lain. Ini memungkinkan beberapa kemunculan nama pengguna. Setiap kejadian dapat memiliki kata sandi yang berbeda atau tanpa kata sandi. Hal ini memungkinkan pengguna 'dbuser' untuk login secara lokal (dbuser @ localhost) tanpa menggunakan kata sandi dan pengguna yang sama login dari server lain dalam netblock yang diberikan (dbuser@'10.1.2.20 ') dengan kata sandi seperti' pass1 'dan pengguna untuk login dari jarak jauh dari mana saja (dbuser @ '%') dengan kata sandi jarak jauh seperti 'pass2'.

Mengingat algoritma otentikasi yang digunakan MySQL, tidak ada batasan yang ditempatkan pada pengguna dengan ada atau tidak adanya kata sandi.

Inilah sebabnya mengapa Panduan Studi Sertifikasi MySQL 5.0 mengatakan pada Halaman 498 Paragraf 6 di bulletpointsnya mengungkap cara membersihkan proses otentikasi:

Di Unix, MySQL dilengkapi dengan skrip mysql_secure_installation yang dapat melakukan beberapa operasi terkait keamanan yang bermanfaat pada instalasi Anda. Script memiliki kemampuan sebagai berikut:

  • Tetapkan kata sandi untuk akun root
  • Hapus semua akun root yang dapat diakses dari jarak jauh.
  • Hapus akun pengguna anonim. Ini meningkatkan keamanan karena mencegah kemungkinan siapa pun terhubung ke server MySQL sebagai root dari host jarak jauh. Hasilnya adalah siapa pun yang ingin terhubung sebagai root harus terlebih dahulu dapat masuk pada host server, yang memberikan penghalang tambahan terhadap serangan.
  • Hapus database pengujian (Jika Anda menghapus akun anonim, Anda mungkin juga ingin menghapus database pengujian yang mereka akses).
RolandoMySQLDBA
sumber
Ya saya mencoba, itu mengembalikan baris tanpa kata sandi. Terima kasih atas penjelasan Anda yang luar biasa dan merekomendasikan buku sertifikasi MySQL.
Baru belajar
2
Rolando, jika dua nama pengguna yang identik ada di tabel mysql.user, satu dengan kata sandi dan satu tanpa, apakah itu berarti bahwa MySQL menolak otentikasi ketika tidak menggunakan kata sandi?
Craig Efrein
@Craig - Pertanyaan Anda sangat penting. Saya akan mentransfernya ke jawaban saya dan mengatasinya di sana.
RolandoMySQLDBA
Terima kasih atas jawaban terinci, dalam kasus saya, saya memiliki beberapa pengguna yang entah bagaimana dikonfigurasi.
SoWeLie
@RolandoMySQLDBA, dapatkah semua informasi dalam panduan studi sertifikasi sudah ditemukan di manual online MySQL?
Pacerier
5

Wildcard host '%' tidak cocok dengan 'localhost'. Secara default, klien mysql akan mencoba untuk terhubung melalui soket daripada tcp (biasanya beberapa tempat seperti /var/lib/mysql/mysql.sock).

Anda dapat mengubah dana bantuan menjadi 'a' @ 'localhost', atau memaksa klien untuk beroperasi melalui tumpukan TCP seperti:

mysql -u a -p --protocol=TCP
atxdba
sumber
Saya mencoba, tetapi masih tidak berhasil.
Baru belajar
Bagaimana cara mengkonfigurasi opsi ini my.cnfagar tidak perlu lagi menggunakan parameter ini?
shgnInc
1
Kamu tidak. Jika Anda tidak menentukan nama host -h ia menganggap "localhost" yang berarti ia mencari soket, bukan port TCP tanpa flag protokol. Anda bisa mengatur alias shell jika Anda lelah mengetik semua argumen.
atxdba
2

Apakah Anda memeriksa untuk memastikan bahwa MySQL benar-benar mendengarkan pada 3306? Jalankan netstat -tlpn dan berikan hasilnya. Jika Anda tidak melihat 3306 maka mungkin tidak.

Di my.cnf Anda harus memverifikasi bahwa --skip-networking dikomentari

[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
Craig Efrein
sumber
Saya juga melakukan hal yang sama seperti yang ditanyakan dalam pertanyaan. dan juga melakukan apa yang Anda katakan dalam jawaban Anda tetapi masih ada masalah yang sama.
Abdul Manaf
Bisakah Anda memberikan hasil dari permintaan berikut: pilih pengguna, host dari mysql.user;
Craig Efrein
Ya, MySQL mendengarkan pada port 3306. Lihat hasil edit saya.
Baru belajar
Anda juga mungkin ingin mencoba pengguna mysql -u -p -h 127.0.0.1. Jika itu berhasil maka saya percaya mysql-nya yang tidak tahu bagaimana menyelesaikan localhost. Entri untuk localhost yang menunjuk ke 127.0.0.1 di file / etc / hosts Anda akan menyelesaikannya.
Craig Efrein
Apakah Anda menjalankan Flush Privileges?
Craig Efrein
1

Seperti yang dijelaskan oleh @atxdba, Untuk menghubungkan daemon mysql dari jarak jauh yang tidak terhubung melalui soket, maka Anda harus terhubung dari jarak jauh melalui TCP.

Untuk ini, Anda harus menentukan --protocol=TCPper setiap koneksi. Meskipun, Anda dapat mengaturnya di my.cnfserver:

[client]
protocol=tcp
shgnInc
sumber