Skip to content
VDS · Cơ sở dữ liệu

Người dùng và quyền trong cơ sở dữ liệu

Cách tạo người dùng riêng cho từng ứng dụng trong MySQL và PostgreSQL, cấp quyền tối thiểu và kiểm tra rằng không có gì thừa được cho phép.

Cập nhật 23 tháng 8, 2026

Một ứng dụng chạy dưới quyền root hoặc postgres sẽ giao toàn bộ cơ sở dữ liệu trên máy cho kẻ tấn công ngay từ lỗ hổng đầu tiên. Một người dùng riêng chỉ có quyền trên schema của chính nó sẽ giới hạn thiệt hại trong một dự án.

MySQL và MariaDB

Người dùng ở đây là một cặp “tên và host”, và đây chính là nguồn gốc của sự nhầm lẫn:

CREATE USER 'shop'@'localhost' IDENTIFIED BY 'long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'shop'@'localhost';
FLUSH PRIVILEGES;

'shop'@'localhost' và 'shop'@'%' là hai người dùng khác nhau với mật khẩu khác nhau. Đừng tạo bản ghi với host % trừ khi cần thiết: nó cho phép đăng nhập từ bất kỳ địa chỉ nào.

Quyền trên cấu trúc chỉ cần trong quá trình migration:

GRANT CREATE, ALTER, DROP, INDEX, REFERENCES ON shop.* TO 'shop_migrate'@'localhost';

Tách vai trò ứng dụng và vai trò migration là một thực hành tốt: khi đó một truy vấn thông thường về mặt vật lý không thể xóa bảng.

Kiểm tra:

SELECT user, host FROM mysql.user;
SHOW GRANTS FOR 'shop'@'localhost';

Đổi mật khẩu và xóa:

ALTER USER 'shop'@'localhost' IDENTIFIED BY 'new-password';
DROP USER 'shop'@'localhost';

PostgreSQL

Vai trò và các quyền của nó trên cơ sở dữ liệu và schema:

CREATE ROLE shop WITH LOGIN PASSWORD 'long-random-password';
CREATE DATABASE shop OWNER shop;
REVOKE ALL ON DATABASE shop FROM PUBLIC;

Đối với vai trò chỉ đọc (báo cáo, phân tích, bảng điều khiển giám sát):

CREATE ROLE reader WITH LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE shop TO reader;
GRANT USAGE ON SCHEMA public TO reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO reader;

Dòng cuối cùng là bắt buộc: nếu không có nó, vai trò sẽ không thấy các bảng được tạo sau khi cấp quyền, và trong một tháng các báo cáo sẽ hỏng trên dữ liệu mới.

Kiểm tra:

\du
\l
\dp

Những gì phải được khóa chặt

  • Không có vai trò ứng dụng nào là superuser.
  • Mỗi dự án có cơ sở dữ liệu riêng và người dùng riêng.
  • Mật khẩu dài và ngẫu nhiên, và khác nhau cho các dự án khác nhau.
  • Đăng nhập từ bên ngoài chỉ được phép cho những địa chỉ cần nó — truy cập từ xa.
  • MySQL không có người dùng ẩn danh và không có cơ sở dữ liệu test: mariadb-secure-installation làm việc này.

Lỗi thường gặp

Triệu chứngNguyên nhân
Access denied với mật khẩu đúngMột quy tắc host khác đã khớp, ví dụ ''@'localhost'
Đã cấp quyền, nhưng SELECT không hoạt độngPostgreSQL thiếu USAGE ON SCHEMA
Bảng mới không hiển thị với vai tròDEFAULT PRIVILEGES chưa được đặt
Ứng dụng đã xóa mọi thứ trong một migration thất bạiVai trò ứng dụng có quyền DROP
Mật khẩu hiển thị trong lịch sử lệnhĐặt mật khẩu từ một tệp, xóa ~/.mysql_history

Hãy lưu mật khẩu cơ sở dữ liệu trong tệp môi trường của dịch vụ với quyền 600, không lưu trong mã nguồn. Nếu bị xâm phạm, bạn đổi một dòng và khởi động lại, chứ không phải xây dựng lại toàn bộ dự án.