Bảo mật web/API thực dụng: auth, session, rate limit và dữ liệu đầu vào
Bảo mật

Bảo mật web/API thực dụng: auth, session, rate limit và dữ liệu đầu vào

Nam Nguyen
5 phút đọc
0 lượt xem
#security
#api
#auth
#rate-limit

Bảo mật bắt đầu từ các lỗi rất đời thường#

Nhiều sự cố bảo mật không đến từ kỹ thuật tấn công quá phức tạp. Chúng đến từ token bị commit lên Git, endpoint admin thiếu kiểm tra quyền, input không được validate, session cookie cấu hình sai, log chứa dữ liệu nhạy cảm, hoặc API trả quá nhiều field. Vì vậy bảo mật thực dụng là xây các lớp phòng vệ cơ bản và kiểm tra chúng đều đặn.

Một backend an toàn không chỉ có authentication. Nó cần authorization, validation, output filtering, rate limiting, audit trail, secret management và quy trình phản ứng khi có sự cố.

Authentication và authorization là hai chuyện khác nhau#

Authentication trả lời "người này là ai". Authorization trả lời "người này được làm gì". Một user đã đăng nhập không có nghĩa là họ được sửa mọi bài viết, xem mọi đơn hàng hoặc gọi mọi endpoint admin.

  • Authentication: login bằng password, OAuth, magic link, SSO hoặc API key.
  • Authorization: role, permission, ownership, policy theo resource.

Trong API, hãy kiểm tra quyền ở phía server cho từng mutation quan trọng. Frontend ẩn nút "Delete" chỉ là UX, không phải bảo mật.

Session cookie phù hợp web app truyền thống hoặc dashboard admin vì browser tự gửi cookie theo domain. Cookie nên có HttpOnly, Secure, SameSite và thời hạn hợp lý. HttpOnly giúp JavaScript không đọc được token; Secure yêu cầu HTTPS; SameSite giảm rủi ro CSRF.

JWT phù hợp khi cần token tự chứa thông tin, nhiều service xác minh độc lập hoặc API client không dùng cookie. Nhưng JWT khó revoke nếu không có blacklist hoặc token version. Đừng chọn JWT chỉ vì nó "hiện đại". Hãy chọn theo mô hình client, khả năng revoke và cách quản lý quyền.

Validate input theo allowlist#

Input từ user, webhook, query string và admin form đều không đáng tin. Validation tốt nên giới hạn kiểu dữ liệu, độ dài, format, enum và relationship. Với HTML content, cần sanitize để loại bỏ script, event handler và URL nguy hiểm.

TypeScript
type PostInput = {
  title: string;
  slug: string;
  content: string;
  published_at: string | null;
};

function isValidSlug(value: string) {
  return /^[a-z0-9-]+$/.test(value) && value.length <= 120;
}

Allowlist tốt hơn blacklist. Thay vì cố đoán mọi chuỗi độc hại, hãy định nghĩa chính xác dữ liệu hợp lệ là gì. Database constraint cũng nên lặp lại các rule quan trọng như unique slug, foreign key và giới hạn trạng thái.

Output filtering giảm rò rỉ dữ liệu#

Không phải field nào trong database cũng nên trả về public API. Ví dụ comment có thể có email người gửi, nhưng public API chỉ nên trả tên, nội dung đã duyệt và timestamp. User profile public không nên trả password hash, refresh token, provider id nội bộ hoặc audit note.

Hãy tạo select list rõ ràng cho public route thay vì select *. Với admin route, vẫn nên giới hạn theo nhu cầu màn hình để tránh vô tình lộ dữ liệu khi UI đổi.

Rate limit và abuse protection#

Endpoint login, contact form, comment form, search và file upload đều dễ bị abuse. Rate limit nên đặt theo IP, user id hoặc API key tùy ngữ cảnh. Với login, cần thêm lockout mềm, delay tăng dần hoặc captcha sau nhiều lần sai. Với contact/comment, cần kiểm tra độ dài, honeypot hoặc moderation.

Rate limit không chỉ bảo vệ hạ tầng. Nó còn bảo vệ chi phí nếu endpoint gọi AI API, gửi email hoặc xử lý upload nặng.

Secret management#

Secret không được commit vào Git và không được đóng gói vào frontend bundle. Phân biệt biến public và private. Trong Next.js, biến có tiền tố public sẽ được expose cho client nếu dùng trong browser. Service role key, database password, signing secret và private API key phải chỉ tồn tại phía server.

  • Dùng secret manager của nền tảng deploy.
  • Rotate secret khi nghi ngờ lộ.
  • Giới hạn quyền của key theo nhu cầu thực tế.
  • Không log secret hoặc header authorization.
  • Scan repository để phát hiện secret trước khi push.

Security headers đáng bật#

Security headers không thay thế code an toàn, nhưng chúng giảm tác động của một số lỗi. Các header phổ biến gồm X-Content-Type-Options, Referrer-Policy, Permissions-Policy, Content-Security-Policy và X-Frame-Options hoặc frame-ancestors trong CSP.

CSP mạnh nhưng cần triển khai cẩn thận vì có thể làm hỏng script, image hoặc style hợp lệ. Hãy bắt đầu bằng report-only ở hệ thống lớn, theo dõi violation rồi siết dần.

Audit log cho hành động nhạy cảm#

Admin login, đổi quyền, xóa dữ liệu, publish bài, thay đổi billing hoặc export dữ liệu nên có audit log. Audit log nên ghi ai làm, làm gì, resource nào, khi nào, IP hoặc user agent nếu hợp lý. Đừng ghi password, token hoặc dữ liệu nhạy cảm không cần thiết.

Khi xảy ra sự cố, audit log giúp bạn trả lời câu hỏi quan trọng: phạm vi ảnh hưởng là gì và hành động nào đã diễn ra.

Checklist bảo mật cho web/API#

  • Mọi mutation quan trọng đều kiểm tra authentication và authorization phía server.
  • Session cookie có HttpOnly, Secure, SameSite và expiration.
  • Input được validate theo allowlist và giới hạn độ dài.
  • Public API không trả field nhạy cảm.
  • Endpoint dễ bị abuse có rate limit.
  • Secret không nằm trong Git, frontend bundle hoặc log.
  • Database có constraint bảo vệ dữ liệu quan trọng.
  • Admin action có audit log.
  • Error message không lộ stack trace hoặc chi tiết nội bộ ở production.

Bảo mật tốt là nhiều lớp nhỏ hoạt động cùng nhau. Không có checklist nào bảo đảm tuyệt đối, nhưng nếu làm chắc các nền tảng này, bạn đã giảm được phần lớn rủi ro phổ biến trong web app và API.

Nguồn tham khảo chính#

Chia sẻ bài viết

Giúp người khác tìm thấy bài viết này

Bình luận

Đang tải bình luận...

Đang tải bình luận...

Để lại bình luận

Email của bạn sẽ không được công khai

Tối thiểu 10 ký tự

0 / 5000