Sử dụng% cho máy chủ khi tạo người dùng MySQL


93

Cơ sở dữ liệu MySQL của tôi cần hai người dùng: người dùng ứng dụng và người hỗ trợ.
Một trong những nhà phát triển ứng dụng khẳng định rằng tôi tạo bốn tài khoản cho những người dùng này:

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

Đối với cuộc sống của tôi, tôi không thể hiểu tại sao anh ấy nghĩ rằng chúng tôi cần điều này. Sẽ không sử dụng ký tự đại diện làm máy chủ quản lý 'localhost'?

Có ý kiến ​​gì không?

(Sử dụng MySQL 5.5 tại đây)

Câu trả lời:


106

localhostlà đặc biệt trong MySQL, nó có nghĩa là kết nối qua ổ cắm UNIX (hoặc các đường ống được đặt tên trên Windows, tôi tin rằng) trái ngược với ổ cắm TCP / IP. Sử dụng %như máy chủ không bao gồm localhost, do đó cần phải chỉ định rõ ràng nó.


Trong phiên bản nào? Trong MySQL 5.5.35, "%" cũng khớp với localhost.
depquid

4
Không chỉ "localhost" kết nối qua local socket, 127.0.0.1 (không sử dụng socket) sẽ không khớp với% mà thay vào đó là localhost. Đã thấy điều đó với cài đặt haproxy ngay hôm nay.
Phillipp

33

Như @nos đã chỉ ra trong các nhận xét về câu trả lời hiện được chấp nhận cho câu hỏi này, câu trả lời được chấp nhận là không chính xác.

Có, có sự khác biệt giữa việc sử dụng %localhostcho máy chủ tài khoản người dùng khi kết nối qua kết nối ổ cắm thay vì kết nối TCP / IP tiêu chuẩn.

Giá trị máy chủ của %không bao gồm localhostcho các ổ cắm và do đó phải được chỉ định nếu bạn muốn kết nối bằng phương pháp đó.


15

Hãy chỉ kiểm tra.

Kết nối với tư cách siêu người dùng, sau đó:

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

và sau đó

USE mysql;

Thiết lập

Tạo người dùng foocó mật khẩu barđể thử nghiệm:

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

Kết nối

Để kết nối với Unix Domain Socket (tức là ống I / O được đặt tên bởi mục nhập hệ thống tệp /var/run/mysqld/mysqld.sockhoặc một số tương tự), hãy chạy điều này trên dòng lệnh (sử dụng --protocoltùy chọn để đảm bảo gấp đôi)

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

Người ta hy vọng rằng các kết quả ở trên khớp với "người dùng đến từ localhost" nhưng chắc chắn không phải "người dùng đến từ 127.0.0.1".

Thay vào đó, để kết nối với máy chủ từ "127.0.0.1", hãy chạy điều này trên dòng lệnh

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

Nếu bạn bỏ qua --protocol=TCP, mysqllệnh sẽ vẫn cố sử dụng ổ cắm miền Unix. Bạn cũng có thể nói:

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

Hai lần thử kết nối trong một dòng:

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"

(mật khẩu được đặt trong môi trường để nó được chuyển đến mysqlquy trình)

Xác minh trong trường hợp nghi ngờ

Để thực sự kiểm tra xem kết nối đi qua ổ cắm TCP / IP hay ổ cắm Miền Unix

  1. lấy PID của quy trình máy khách mysql bằng cách kiểm tra đầu ra của ps faux
  2. chạy lsof -n -p<yourpid>.

Bạn sẽ thấy một cái gì đó như:

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

hoặc là

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

Vì thế:

Trường hợp 0: Máy chủ = '10 .10.10.10 '(kiểm tra rỗng)

update user set host='10.10.10.10' where user='foo'; flush privileges;
  • Kết nối bằng ổ cắm: FAILURE
  • Kết nối từ 127.0.0.1: FAILURE

Trường hợp 1: Máy chủ = '%'

update user set host='%' where user='foo'; flush privileges;
  • Kết nối bằng ổ cắm: OK
  • Kết nối từ 127.0.0.1: OK

Trường hợp 2: Host = 'localhost'

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

Hành vi khác nhau và điều này dường như phụ thuộc vào skip-name-resolve. Nếu được đặt, các dòng có localhostbị bỏ qua theo nhật ký. Bạn có thể thấy điều sau trong nhật ký lỗi: "'mục nhập' người dùng '' root @ localhost 'bị bỏ qua trong chế độ --skip-tên-giải quyết." . Điều này có nghĩa là không có kết nối thông qua Unix Domain Socket. Nhưng theo kinh nghiệm thì không phải như vậy.localhostbây giờ chỉ có nghĩa là Ổ cắm tên miền Unix và không còn khớp với 127.0.0.1 nữa.

skip-name-resolve No tăt rôi:

  • Kết nối bằng ổ cắm: OK
  • Kết nối từ 127.0.0.1: OK

skip-name-resolve là trên:

  • Kết nối bằng ổ cắm: OK
  • Kết nối từ 127.0.0.1: FAILURE

Trường hợp 3: Máy chủ = '127.0.0.1'

update user set host='127.0.0.1' where user='foo';flush privileges;
  • Kết nối bằng ổ cắm: FAILURE
  • Kết nối từ 127.0.0.1: OK

Trường hợp 4: Máy chủ = ''

update user set host='' where user='foo';flush privileges;
  • Kết nối bằng ổ cắm: OK
  • Kết nối từ 127.0.0.1: OK

(Theo MySQL 5.7: 6.2.4 Access Control, Giai đoạn 1: Xác minh kết nối , Chuỗi trống '' cũng có nghĩa là "bất kỳ máy chủ lưu trữ nào" nhưng sắp xếp sau '%'. )

Trường hợp 5: Máy chủ = '192.168.0.1' (kiểm tra thêm)

('192.168.0.1' là một trong những địa chỉ IP trên máy của tôi, hãy thay đổi phù hợp trong trường hợp của bạn)

update user set host='192.168.0.1' where user='foo';flush privileges;
  • Kết nối bằng ổ cắm: FAILURE
  • Kết nối từ 127.0.0.1: FAILURE

nhưng

  • Kết nối bằng mysql -pbar -ufoo -h192.168.0.1: OK (!)

Cái sau vì đây thực sự là kết nối TCP đến từ 192.168.0.1, như được tiết lộ bởi lsof:

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

Trường hợp cạnh A: Máy chủ = '0.0.0.0'

update user set host='0.0.0.0' where user='foo';flush privileges;
  • Kết nối bằng ổ cắm: FAILURE
  • Kết nối từ 127.0.0.1: FAILURE

Trường hợp cạnh B: Host = '255.255.255.255'

update user set host='255.255.255.255' where user='foo';flush privileges;
  • Kết nối bằng ổ cắm: FAILURE
  • Kết nối từ 127.0.0.1: FAILURE

Trường hợp cạnh C: Host = '127.0.0.2'

(127.0.0.2 là địa chỉ lặp lại hoàn toàn hợp lệ tương đương với 127.0.0.1 như được định nghĩa trong RFC6890 )

update user set host='127.0.0.2' where user='foo';flush privileges;
  • Kết nối bằng ổ cắm: FAILURE
  • Kết nối từ 127.0.0.1: FAILURE

Một cách thú vị:

  • mysql -pbar -ufoo -h127.0.0.2kết nối từ 127.0.0.1và đang THẤT BẠI
  • mysql -pbar -ufoo -h127.0.0.2 --bind-address=127.0.0.2 ổn

Dọn dẹp

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

Phụ lục

Để xem những gì thực sự có trong mysql.userbảng, là một trong những bảng quyền, hãy sử dụng:

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;

điều này mang lại:

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

Tương tự cho bảng 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;

6
Điều này cần một kết luận làm rõ những gì phần còn lại của câu trả lời thực sự đang nói mà không cần hiểu mã.
Prometheus

7

Nếu bạn muốn kết nối với user@'%'sử dụng localhost mysql -h192.168.0.1 -uuser -p.


5

Sẽ cung cấp một câu trả lời hơi khác so với những câu được cung cấp cho đến nay.

Nếu bạn có một hàng cho người dùng ẩn danh từ máy chủ cục bộ trong bảng người dùng của mình ''@'localhost'thì hàng này sẽ được coi là cụ thể hơn người dùng của bạn với máy chủ lưu trữ ký tự đại diện 'user'@'%'. Đây là lý do tại sao nó là cần thiết để cung cấp 'user'@'localhost'.

Bạn có thể xem điều này được giải thích chi tiết hơn ở cuối trang này .


5

Biểu tượng phần trăm có nghĩa là: bất kỳ máy chủ lưu trữ nào, bao gồm các kết nối từ xa và cục bộ.

Máy chủ cục bộ chỉ cho phép các kết nối cục bộ.

(vì vậy để bắt đầu, nếu bạn không cần kết nối từ xa với cơ sở dữ liệu của mình, bạn có thể loại bỏ người dùng appuser @ '%' ngay lập tức)

Vì vậy, có, chúng đang chồng chéo, nhưng ...

... có một lý do để đặt cả hai loại tài khoản, điều này được giải thích trong tài liệu mysql: http://dev.mysql.com/doc/refman/5.7/en/adding-users.html .

Nếu bạn có một người dùng ẩn danh trên máy chủ cục bộ của bạn, bạn có thể phát hiện ra người dùng này với:

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

và nếu bạn chỉ tạo user appuser @ '%' (và bạn không phải appuser @ 'localhost'), thì khi người dùng appuser mysql kết nối từ máy chủ cục bộ, tài khoản người dùng ẩn danh sẽ được sử dụng (nó được ưu tiên hơn appuser @ của bạn '%' người dùng).

Và cách khắc phục cho điều này là (như người ta có thể đoán) tạo appuser @ 'localhost' (cụ thể hơn là người dùng ẩn danh trên máy chủ cục bộ và sẽ được sử dụng nếu người dùng ứng dụng của bạn kết nối từ localhost).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.