Menggunakan% untuk host saat membuat pengguna MySQL

93

Basis data MySQL saya membutuhkan dua pengguna: pengguna aplikasi dan dukungan.
Salah satu pengembang aplikasi bersikeras bahwa saya membuat empat akun untuk pengguna ini:

appuser@'%'
appuser@'localhost'
support@'%'
support@'localhost'

Demi kehidupanku, aku tidak tahu mengapa menurutnya kita membutuhkan ini. Tidakkah menggunakan wildcard sebagai tuan rumah akan mengurus 'localhost'?

Ada ide?

(Menggunakan MySQL 5.5 di sini)

Ed Manet
sumber

Jawaban:

106

localhostkhusus di MySQL, itu berarti koneksi melalui soket UNIX (atau pipa bernama pada Windows, saya percaya) sebagai lawan dari soket TCP / IP. Menggunakan %sebagai tuan rumah tidak termasuk localhost, maka kebutuhan untuk menentukannya secara eksplisit.

aleroot
sumber
Dalam versi apa Di MySQL 5.5.35, "%" juga cocok dengan localhost.
depquid
4
Tidak hanya "localhost" terhubung melalui soket lokal, 127.0.0.1 (yang tidak menggunakan soket) tidak akan cocok dengan% tetapi localhost juga. Lihat itu dengan instalasi haproxy hari ini.
Phillipp
33

Seperti yang ditunjukkan @nos di komentar dari jawaban yang diterima saat ini untuk pertanyaan ini, jawaban yang diterima salah.

Ya, ada perbedaan antara menggunakan %dan localhostuntuk host akun pengguna saat menyambungkan melalui sambungan soket, bukan sambungan TCP / IP standar.

Nilai host %tidak termasuk localhostuntuk soket dan karenanya harus ditentukan jika Anda ingin menyambung menggunakan metode itu.

John Kary
sumber
15

Mari kita uji.

Hubungkan sebagai superuser, lalu:

SHOW VARIABLES LIKE "%version%"; 
+-------------------------+------------------------------+ 
| Variable_name           | Value                        | 
+-------------------------+------------------------------+ 
| version                 | 10.0.23-MariaDB-0+deb8u1-log | 

lalu

USE mysql;

Mendirikan

Buat pengguna foodengan kata sandi baruntuk pengujian:

CREATE USER foo@'%' IDENTIFIED BY 'bar'; FLUSH PRIVILEGES;

Menghubung

Untuk menyambung ke Soket Domain Unix (yaitu pipa I / O yang diberi nama oleh entri sistem file /var/run/mysqld/mysqld.sockatau semacamnya), jalankan ini pada baris perintah (gunakan --protocolopsi untuk memastikan ganda)

mysql -pbar -ufoo
mysql -pbar -ufoo --protocol=SOCKET

Orang mengharapkan bahwa kecocokan di atas "pengguna berasal dari localhost" tetapi tentu saja bukan "pengguna berasal dari 127.0.0.1".

Untuk menyambung ke server dari "127.0.0.1" sebagai gantinya, jalankan ini di baris perintah

mysql -pbar -ufoo --bind-address=127.0.0.1 --protocol=TCP

Jika Anda keluar --protocol=TCP, mysqlperintah akan tetap mencoba menggunakan soket domain Unix. Anda juga bisa mengatakan:

mysql -pbar -ufoo --bind-address=127.0.0.1 --host=127.0.0.1

Dua upaya koneksi dalam satu baris:

export MYSQL_PWD=bar; \
mysql -ufoo --protocol=SOCKET --execute="SELECT 1"; \
mysql -ufoo --bind-address=127.0.0.1 --host=127.0.0.1 --execute="SELECT 1"

(kata sandi diatur di lingkungan sehingga diteruskan ke mysqlproses)

Verifikasi Jika Ada Keraguan

Untuk benar-benar memeriksa apakah koneksi berjalan melalui soket TCP / IP atau soket Domain Unix

  1. dapatkan PID dari proses klien mysql dengan memeriksa output dari ps faux
  2. lari lsof -n -p<yourpid>.

Anda akan melihat sesuatu seperti:

mysql [PID] quux 3u IPv4 [code] 0t0 TCP 127.0.0.1:[port]->127.0.0.1:mysql (ESTABLISHED)

atau

mysql [PID] quux 3u unix [code] 0t0 [code] socket

Begitu:

Kasus 0: Host = '10 .10.10.10 '(tes nol)

update user set host='10.10.10.10' where user='foo'; flush privileges;
  • Hubungkan menggunakan socket: FAILURE
  • Hubungkan dari 127.0.0.1: FAILURE

Kasus 1: Host = '%'

update user set host='%' where user='foo'; flush privileges;
  • Terhubung menggunakan soket: OK
  • Hubungkan dari 127.0.0.1: OK

Kasus 2: Host = 'localhost'

update user set host='localhost' where user='foo';flush privileges;

Perilaku bervariasi dan ini tampaknya tergantung skip-name-resolve. Jika disetel, menyebabkan baris dengan localhostdiabaikan menurut log. Berikut ini dapat dilihat di log kesalahan: "'entri pengguna' root @ localhost 'diabaikan dalam mode - lewati-nama-penyelesaian." . Ini berarti tidak ada koneksi melalui Unix Domain Socket. Tetapi secara empiris tidak demikian. localhostsekarang berarti HANYA Soket Domain Unix, dan tidak lagi cocok dengan 127.0.0.1.

skip-name-resolve tidak aktif:

  • Terhubung menggunakan soket: OK
  • Hubungkan dari 127.0.0.1: OK

skip-name-resolve pada:

  • Terhubung menggunakan soket: OK
  • Hubungkan dari 127.0.0.1: FAILURE

Kasus 3: Host = '127.0.0.1'

update user set host='127.0.0.1' where user='foo';flush privileges;
  • Hubungkan menggunakan socket: FAILURE
  • Hubungkan dari 127.0.0.1: OK

Kasus 4: Host = ''

update user set host='' where user='foo';flush privileges;
  • Terhubung menggunakan soket: OK
  • Hubungkan dari 127.0.0.1: OK

(Menurut MySQL 5.7: 6.2.4 Access Control, Tahap 1: Verifikasi Koneksi , String kosong '' juga berarti "sembarang host" tetapi diurutkan setelah '%'. )

Kasus 5: Host = '192.168.0.1' (tes ekstra)

('192.168.0.1' adalah salah satu alamat IP mesin saya, ubah dengan tepat dalam kasus Anda)

update user set host='192.168.0.1' where user='foo';flush privileges;
  • Hubungkan menggunakan socket: FAILURE
  • Hubungkan dari 127.0.0.1: FAILURE

tapi

  • Hubungkan menggunakan mysql -pbar -ufoo -h192.168.0.1: OK (!)

Yang terakhir karena ini sebenarnya berasal dari koneksi TCP 192.168.0.1, seperti yang diungkapkan oleh lsof:

TCP 192.168.0.1:37059->192.168.0.1:mysql (ESTABLISHED)

Kasus Tepi A: Host = '0.0.0.0'

update user set host='0.0.0.0' where user='foo';flush privileges;
  • Hubungkan menggunakan socket: FAILURE
  • Hubungkan dari 127.0.0.1: FAILURE

Kasus Tepi B: Host = '255.255.255.255'

update user set host='255.255.255.255' where user='foo';flush privileges;
  • Hubungkan menggunakan socket: FAILURE
  • Hubungkan dari 127.0.0.1: FAILURE

Kasus Tepi C: Host = '127.0.0.2'

(127.0.0.2 adalah alamat loopback yang benar-benar valid, setara dengan 127.0.0.1 seperti yang didefinisikan dalam RFC6890 )

update user set host='127.0.0.2' where user='foo';flush privileges;
  • Hubungkan menggunakan socket: FAILURE
  • Hubungkan dari 127.0.0.1: FAILURE

Menariknya:

  • mysql -pbar -ufoo -h127.0.0.2terhubung dari 127.0.0.1dan KEGAGALAN
  • mysql -pbar -ufoo -h127.0.0.2 --bind-address=127.0.0.2 OK

Membersihkan

delete from user where user='foo';flush privileges;

Tambahan

Untuk melihat apa yang sebenarnya ada di mysql.usertabel, yang merupakan salah satu tabel izin, gunakan:

SELECT SUBSTR(password,1,6) as password, user, host,
Super_priv AS su,
Grant_priv as gr,
CONCAT(Select_priv, Lock_tables_priv) AS selock,
CONCAT(Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv) AS modif,
CONCAT(References_priv, Index_priv, Alter_priv) AS ria,
CONCAT(Create_tmp_table_priv, Create_view_priv, Show_view_priv) AS views,
CONCAT(Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) AS funcs,
CONCAT(Repl_slave_priv, Repl_client_priv) AS replic,
CONCAT(Shutdown_priv, Process_priv, File_priv, Show_db_priv, Reload_priv, Create_user_priv) AS admin
FROM user ORDER BY user, host;

ini memberi:

+----------+----------+-----------+----+----+--------+-------+-----+-------+-------+--------+--------+
    | password | user     | host      | su | gr | selock | modif | ria | views | funcs | replic | admin  |
    +----------+----------+-----------+----+----+--------+-------+-----+-------+-------+--------+--------+
    | *E8D46   | foo      |           | N  | N  | NN     | NNNNN | NNN | NNN   | NNNNN | NN     | NNNNNN |

Demikian pula untuk tabel mysql.db:

SELECT host,db,user, 
       Grant_priv as gr,
       CONCAT(Select_priv, Lock_tables_priv) AS selock, 
       CONCAT(Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv) AS modif, 
       CONCAT(References_priv, Index_priv, Alter_priv) AS ria, 
       CONCAT(Create_tmp_table_priv, Create_view_priv, Show_view_priv) AS views, 
       CONCAT(Create_routine_priv, Alter_routine_priv, Execute_priv) AS funcs 
       FROM db ORDER BY user, db, host;
David Tonhofer
sumber
6
Ini membutuhkan kesimpulan yang memperjelas apa yang sebenarnya dikatakan oleh jawaban lainnya tanpa perlu memahami kodenya.
Prometheus
7

Jika Anda ingin terhubung user@'%'dari penggunaan localhost mysql -h192.168.0.1 -uuser -p.

alex
sumber
5

Akan memberikan jawaban yang sedikit berbeda dengan yang diberikan sejauh ini.

Jika Anda memiliki baris untuk pengguna anonim dari localhost di tabel users Anda ''@'localhost'maka ini akan diperlakukan sebagai lebih spesifik daripada pengguna Anda dengan host wildcard 'user'@'%'. Inilah mengapa perlu juga menyediakan 'user'@'localhost'.

Anda dapat melihat penjelasan ini lebih detail di bagian bawah halaman ini .

Joshua Walsh
sumber
5

Simbol persen berarti: semua host, termasuk koneksi jarak jauh dan lokal.

Localhost hanya mengizinkan koneksi lokal.

(jadi untuk memulai, jika Anda tidak memerlukan koneksi jarak jauh ke database Anda, Anda dapat langsung menyingkirkan pengguna appuser @ '%')

Jadi, ya, mereka tumpang tindih, tapi ...

... ada alasan untuk menyetel kedua jenis akun, ini dijelaskan di dokumen mysql: http://dev.mysql.com/doc/refman/5.7/en/adding-users.html .

Jika Anda memiliki pengguna anonim di localhost Anda, yang dapat Anda temukan dengan:

select Host from mysql.user where User='' and Host='localhost';

dan jika Anda hanya membuat pengguna appuser @ '%' (dan Anda bukan appuser @ 'localhost'), maka ketika pengguna appuser mysql terhubung dari host lokal, akun pengguna anonim digunakan (ini lebih diutamakan daripada pengguna aplikasi Anda @ '%' pengguna).

Dan perbaikan untuk ini adalah (seperti yang bisa ditebak) dengan membuat appuser @ 'localhost' (yang lebih spesifik daripada pengguna anonim host lokal dan akan digunakan jika pengguna aplikasi Anda terhubung dari localhost).

ling
sumber